标签:style class blog code java http
在百度百科上是这样介绍枚举的:
在C#或C++,java等一些计算机编程语言中,枚举类型是一种基本数据类型而不是构造数据类型,而在C语言等计算机编程语言中,它是一种构造数据类型。枚举类型用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型。
而在java中,枚举扩大了这一概念,因为在java中,枚举已经称为一个类,因此完全具有类的特性.
我们都知道枚举是JDK1.5才推出的新概念,那么在此之前,我们如果想使用一些固定的常量集合,比如性别(2个),季节(4个),星期(7个)以及一些其他复杂的,我们该如何表示这些呢?我们就以星期来举例说明:
在JDK1.5之前,大多数程序员是使用下面这种方式:
class Enum01 { static final String MONDAY = "星期一"; static final String TUESDAY = "星期一"; static final String WEDNESDAY = "星期一"; static final String THURDAY = "星期一"; static final String FRIDAY = "星期一"; static final String SATURDAY = "星期一"; static final String SUNDAY = "星期一"; }
System.out.println("今天是"+Enum01.THURDAY); System.out.println("明天是"+Enum01.FRIDAY);但是当我们需要处理一些特殊问题的时候,随之而来的问题就出现了,假如这个常量集合很大,难道我们就必须在Enum01类中写许多行类似static final String MONDAY = "星期一";这样的代码,这样的重复工作我们无法接收,也不符合java的复用思想.如果我们想要遍历它的常量集合该怎么办呢?很遗憾,这无法做到,致命的是,如果我们在有些时候不想使用字符串来表达星期,而是想使用整型常量来表示的话,我们该怎么解决呢?修改----但是修改带来的问题就更大了,...这些都是没有出现枚举而带来的问题.
enum Enum2 { MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY("星期三"), THURDAY("星期四"), FRIDAY( "星期五"), SATURDAY("星期六"), SUNDAY("星期日"); private String weekday; public String getWeekday() { return this.weekday; } Enum2(String weekday) { this.weekday = weekday; } }
for (Enum2 en : Enum2.values()) { System.out.println(en.getWeekday()); }
注意:enum类只能有一个受保护(并非protected修饰)的构造函数,并且程序员无法进行调用
上面的内容都不是干货,看上去既无味也没什么实际说明,下面我们给出一个能够在实际生活中用到的情况.
假如一家超市在出售几种类型的水果,apple(苹果),banana(香蕉), (菠萝),watermelon(西瓜),grape(葡萄),我们就以这五种水果来举例:
代码如下:
enum Fruits{ apple(3.24),banana(2.34),pineapple(4.23),watermelon(2.5),grape(1.2); private double price; public double getPrice() { return this.price; } public void setPrice(double price) { this.price = price; } private Fruits(double price) { this.price = price; } }
class Customer{ public double buy(Fruits type,double weight){ return type.getPrice()*weight; } }
回值是购买该水果所花费的金额.
下面进行测试,
Customer xiaoming = new Customer(); double cost = 0 ; cost = xiaoming.buy(Fruits.apple, 1);//小明购买了2斤苹果 cost += xiaoming.buy(Fruits.banana, 2);//小明购买了2斤香蕉 cost += xiaoming.buy(Fruits.grape, 3);//小明购买了2斤葡萄 cost += xiaoming.buy(Fruits.pineapple, 4);//小明购买了2斤菠萝 cost += xiaoming.buy(Fruits.watermelon, 5);//小明购买了西瓜 //计算小明一共所花的金额 System.out.println("结账,您一共花费了"+cost+"元");这样,我们就把客户和水果类聚合在一起了,轻松得到不同用户购买多种不同水果所花费的金钱了,但是这样仍然不是我想
说明的,就像上面所说的,一家商店不可能只出售这么几种水果,也不可能保存水果始终在这个价格,假如下一个礼拜商店新
进了几种水果,而且要进行促销(假如是五一黄金期),那么商店比如会重新改动该枚举类,并且要增加新的水果和改变原有水
果的价格,但是--显然,这不是一种好的处理方案,我们不能在原有的类中进行修改,在语言本身上,这不符合开闭原则(既一个类
对扩展开放,而对修改关闭).从显示角度上说,也不符合现实生活,如果促销期一过,我们需要将水果价钱恢复到促销前呢?那么
修改后的类显然无法做到这点.因此,我们有必要新建一个扩展枚举类,但是随之而来的问题出现了,java中的枚举类都已经默认
实现了java.lang.Enum类,因此无法进行多继承,那么该怎么半呢?
enum OnSalesFruits{ apple(2.24),banana(1.34),pineapple(3.23),watermelon(1.5),grape(0.2),mango(2.5);//mango为新增 private double price; public double getPrice() { return this.price; } public void setPrice(double price) { this.price = price; } private OnSalesFruits(double price) { this.price = price; } }该扩展类中,我们将原有的水果价格都进行了降价处理,而且新增了一个mango(芒果)种类.
下面.客户小明又来买水果了.
System.out.println("促销前小明购买水果:"); Customer xiaoming = new Customer(); double cost1 = 0 ; cost1 = xiaoming.buy(Fruits.apple, 1);//小明购买了2斤苹果 cost1 += xiaoming.buy(Fruits.banana, 2);//小明购买了2斤香蕉 cost1 += xiaoming.buy(Fruits.grape, 3);//小明购买了2斤葡萄 cost1 += xiaoming.buy(Fruits.pineapple, 4);//小明购买了2斤菠萝 cost1 += xiaoming.buy(Fruits.watermelon, 5);//小明购买了西瓜 //计算小明一共所花的金额 System.out.println("结账,您一共花费了"+cost1+"元"); System.out.println("促销后小明购买水果:"); double cost2 = 0 ; cost2 = xiaoming.buy(OnSalesFruits.apple, 1);//小明购买了2斤苹果 cost2 += xiaoming.buy(OnSalesFruits.banana, 2);//小明购买了2斤香蕉 cost2 += xiaoming.buy(OnSalesFruits.grape, 3);//小明购买了2斤葡萄 cost2 += xiaoming.buy(OnSalesFruits.pineapple, 4);//小明购买了2斤菠萝 cost2 += xiaoming.buy(OnSalesFruits.watermelon, 5);//小明购买了5斤西瓜 cost2 +=xiaoming.buy(OnSalesFruits.mango, 5);//小明购买6斤芒果 System.out.println("结账,您一共花费了"+cost2+"元");
结果如下:
但是这样我们很不满意,因为并没能去继承Fruits类让人很失望,不过,这也从侧面说明了一个问题,那就是枚举不适合
做那些需要改变数据的集合,因此也回到了枚举的定义上:
枚举类:包含常量集合的容器,因此如果发现你创建的类中的值需要变化,那么不建议使用枚举,因为他无法实现
扩展(继承意义上的扩展);
下面说道真正使用枚举类的情况:
假如我们有一串常量需要表示单位换算,比如从千克到磅,到克拉,到盎司,我们知道这些转换率不像如今的货币换算一样
会发生变化,它们的转换率是不变的,因此我们可以创建一个枚举来表示:
enum Converter{ Kg(0.45359237), Cart(2267.96185), Gms(453.59237) ,Ounce(16); private final double symbol ; public double getSymbol() { return this.symbol; } Converter(double sybol){ this.symbol =sybol; } }
class ExchangeUtil{ public static double kgToPound(Converter1 type,double d){ return type.getSymbol() *d; } public static double cartToPound(Converter1 type,double d){ return type.getSymbol() *d; } public static double gmsToPound(Converter1 type,double d){ return type.getSymbol() *d; } public static double ounceToPound(Converter1 type,double d){ return type.getSymbol() *d; } }
这样,我们就可以使用上述代码来完成我们由磅到千克,克拉,盎司的转换了.
测试代码:
System.out.println("100千克转换成磅后为:"+ExchangeUtil.kgToPound(Converter1.Kg, 100)+"磅");
从百度工具上测试结果:
发现很好的吻合了.但是这中方法需要建立两个类,很麻烦,那么有没有简单的方法呢?有--一个枚举类就可以实现:
我们修改原有的Converter类,
enum Converter{ KgToPound("KG"){ @Override double performConversion(double f){ return f*0.45359237; } }, CartToPound("cart"){ @Override double performConversion(double f){ return f*2267.96185; } }, GmsToPound("gms"){ @Override double performConversion(double f){ return f*453.59237; } }, OunceToPound("ounce"){ @Override double performConversion(double f){ return f*16; } }; private final String symbol; public String getSymbol() { return this.symbol; } Converter(String symbol){ this.symbol = symbol; } abstract double performConversion(double f); }
也许很奇怪,我们可以从类中定义抽象方法,并且在类本身中去实现它,这就是java中枚举的新特性,因为在其他语言中无法
实现将方法添加到枚举中,二java为了让枚举实现类的特点,突破了传统枚举的定义,我们可以在枚举类中实现自定义的
抽象方法,但是也有限制,那就是该枚举类中所有的常量都必须实现该抽象方法.
这样一来,我们再进行转换的时候,就无需新创建一个工具类来实现转换功能了.
System.out.println("100千克转换成磅后为:"+Converter.KgToPound.performConversion(100.0)+"磅");
身来实现转换功能,而前述中的代码却需要引入一个工具类,增加了系统的耦合度.
将枚举说道这里,基本差不多了,就剩下了常用枚举的方法,以及枚举的序列化,
至于枚举的序列化和普通类的序列化没什么区别,如果感兴趣可以看看:java对象序列化小结
而枚举常用的方法,这里要说明两个 一个是ordinal,一个是compareTo
ordinal就是返回当前枚举在原有常量序列中的序列号
compareTo就是比较枚举类中两个常量的相对位置
至此,枚举小结.
标签:style class blog code java http
原文地址:http://blog.csdn.net/u012332735/article/details/30247091