枚举类型是Java 5中新增特性的⼀部分,它是⼀种特殊的数据类型,之所以特殊是因为它既是⼀种类(class)类型却⼜⽐类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。
枚举在各个语⾔当中都有着⼴泛的应⽤,通常⽤来表示诸如颜⾊、⽅式、类别、状态等等数⽬有限、形式离散、表达⼜极为明确的量。Java从JDK5开始,引⼊了对枚举的⽀持。
在枚举出现之前,如果想要表示⼀组特定的离散值,往往使⽤⼀些常量。例如:
public class Entity {
public static final int VIDEO = 1;//视频
public static final int AUDIO = 2;//⾳频
public static final int TEXT = 3;//⽂字
public static final int IMAGE = 4;//图⽚
private int id;
private int type;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
例如,针对上述的Entity类,如果要对Entity对象的type属性进⾏赋值,⼀般会采⽤如下方法:
Entity e = new Entity();
e.setId(10);
//e.setType(2);
//⽽这样的话,问题⼜来了。这样做,客户端必须对这些常量去建⽴理解,才能了解如何去使⽤这个东⻄。
//说⽩了,在调⽤的时候,如果⽤户不到Entity类中去看看,还真不知道这个参数应该怎么传、怎么调
e.setType(Entity.AUDIO);
这样做的缺点有:
(1)代码可读性差、易⽤性低。由于setType()⽅法的参数是int型的,在阅读代码的时候往往会让读者感到⼀头雾⽔,根本不明⽩这个2到底是什么意思,代表的是什么类型。
(2)类型不安全。在⽤户去调⽤的时候,必须保证类型完全⼀致,同时取值范围也要正确。像是setType(-1)这样的调⽤是合法的,但它并不合理,今后会为程序带来种种问题。
(3)耦合性⾼,扩展性差。假如,因为某些原因,需要修改Entity类中常量的值,那么,所有⽤到这些常量的代码也就都需要修改——当然,要仔细地修改,万⼀漏了⼀个,那可不是开玩笑的。同时,这样做也不利于扩展。
枚举(在Jave中简称为enum)是⼀个特定类型的类。所有枚举都是Java中的新类
java.lang.Enum的隐式⼦类。此类不能⼿⼯进⾏⼦类定义。⼀个简单的枚举可以是这样:
public enum TypeEnum {
VIDEO,AUDIO,TEXT,IMAGE;
}
上⾯的Entity类就可以改成这样:
public class Entity2 {
private int id;
private TypeEnum type;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public TypeEnum getType() {
return type;
}
public void setType(TypeEnum type) {
this.type = type;
}
}
在为Entity对象赋值的时候,就可以这样:
Entity2 e = new Entity2();
e.setId(10);
e.setType(TypeEnum.AUDIO);
在调⽤setType()时,可选值只有四个,否则会出现编译错误,因此可以看出,枚举是类型安全的,不会出现取值范围错误的问题。同时,客户端不需要建⽴对枚举中常量值的了解,使⽤起来很⽅便,并且可以容易地对枚举进⾏修改,⽽⽆需修改客户端。如果常量从枚举中被删除了,那么客户端将会失败并且将会收到⼀个错误消息。
在Java中⼀个枚举就是⼀个类,它也可以有属性和⽅法,并且实现接⼝。只是所有的枚举都继承⾃java.lang.Enum类,因此enum不可以再继承其他的类。
下⾯给出在枚举中声明属性和⽅法的示例:
public enum TypeEnum {
VIDEO(1), AUDIO(2), TEXT(3), IMAGE(4);
int value;
TypeEnum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
如果要为每个枚举值指定属性,则在枚举中必须声明⼀个参数为属性对应类型的构造⽅法(不能是public)。否则编译器将给出The constructor TypeEnum(int, String) is undefined的错误。在此例中,属性为int型,因此构造⽅法应当为int型。除此之外,还可以为枚举指定多个属性
枚举构造器为什么不能是public?
如果其含有public构造器,那么在类的外部就可以通过这个构造器来新建实例,显然这时实例的数量和值就不固定了,这与定义枚举类的初衷相⽭盾,为了避免这种形象,就对枚举类的构造器默认使⽤private修饰。如果为枚举类的构造器显式指定其它访问控制符,则会编译出错
public enum TypeEnum {
VIDEO(1, "视频"), AUDIO(2, "⾳频"), TEXT(3, "⽂本"), IMAGE(4, "图像");
int value;
String name;
TypeEnum(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
}