一、枚举类的概念
在某些情况下,一个类的对象是有限且固定的,比如季节类,它只有4个对象;再比如性别类,它只有两个对象。这种实例有限且固定的类,在Java中被称为枚举类。
枚举类实际上是一种特殊的类,它由关键字enum定义(与class、interface关键字地位相同),可以有自己的Field、方法、可以实现一个或者多个接口,也可以定义自己的构造器(只能是私有的)。
一个Java源文件中最多只能定义一个public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同,编译之后会生成同名的class文件。
二、枚举类与普通类的区别
- 枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是继承Object类。
- 使用enum定义、非抽象的枚举类默认会使用final修饰 ,因此枚举类不能派生子类。
- 枚举类的构造器只能使用private访问控制符,如果省略了构造器的访问控制符,则默认使用private修饰;如果强制指定访问控制符,则只能指定private修饰符。
- 枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无须程序员显式添加。
public enum Season{
//在第一行列出4个枚举实例,以,分隔
SPRING,SUMMER,FALL,WINTER; //静态常量一般大写
}
三、在switch中使用枚举类
如果需要使用某个枚举类的某个实例,则可使用EnumClass.variable的形式,但在switch中可以直接使用枚举值
public class EnumClass{
public void judge(Season s){
//switch语句里的表达式可以是枚举值
switch(s){
case SPRING : System.out.println("春天");break;
case SUMMER : System.out.println("夏天");break;
case SUMMER : System.out.println("秋天");break;
case SUMMER : System.out.println("冬天");
}
}
public static void main(String[] args){
for(Season s : Season.values()){
System.out.println(s); //可以直接打印枚举值
}
//平常使用枚举实例时
//总是通过EnumClass.variable的形式来访问
new EnumClass().judge(Season.SPRING);
}
}
该类通过values方法返回了Season枚举类的所有实例,并通过循环迭代输出了Season枚举类 的所有实例。
四、枚举类的Field、方法和构造器(不常用)
枚举类也是一种类,只是它是一种比较特殊的类,因此它一样可以定义Field、方法。只不过枚举类通常会被设计为不可变类,所以,我们应该将枚举类的Field都使用private final修饰,这样代码更安全且简洁。
public enum Gender{
//此处的枚举值必须调用对应的构造器来创建
//如果没有无参构造器,列出枚举值是就必须传入参数
MALE("男"),FEMALE("女");
private final String name;
//枚举类的构造器只能使用private修饰,默认也是private
private Gender(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
从此例可知,在枚举类中列出枚举值时,实际上就是调用构造器创建枚举类对象,只是这里无须使用new关键字,也无须显式调用构造器。上面那个Season中列出枚举值时无须传入参数,甚至无须使用括号,是因为其中包含默认的无参构造器。
五、实现接口的枚举类(不常用)
枚举类也可以实现一个或多个接口
public interface GenderDesc{
void showInfo();
}
public enum Gender implements GenderDesc{
//其他部分与四中的Gender一样
...
//实现接口中的showInfo方法
public void showInfo(){
System.out.println("枚举类");
}
}
如果由枚举类来实现接口里的方法,每个枚举值在调用该方法时都有相同的行为方式(因为方法体一样)。如果需要每个枚举值在调用该方法时呈现不同的行为方式时,可以在*公共实现方法中使用switch(this)*做判断或者每个实例分别实现该方法。
注: switch(this)比较推荐,因为实例多的情况,没开写代码冗余太高。实例少的情况,推荐分开实现
public enum Gender implements GenderDesc{
//此处的枚举值必须调用对应的构造器来创建
MALE("男"){ //花括号这是匿名内部类的写法
public void showInfo(){
System.out.println("男性的枚举方法");
}
}
FEMALE("女"){
public void showInfo(){
System.out.println("女性的枚举方法");
}
}
}
这里就是分开实现,不推荐这种写法,更推荐switch判断