一、介绍
枚举的思想很简单,也很方便:它代表了一组固定的常量值。实际开发应用中,枚举经常用来设计一些状态常量。
比如,星期几就是枚举的一个最好例子,因为他们被限制在周一、周二、周三、周四、周五、 周六和周日。
二、枚举是一种特殊的类
在枚举被引入Java语言之前,在Java中模拟一组固定值的常规方法是通过声明一组常量。例如:
public class DaysOfTheWeekConstants {
public static final int MONDAY = 0;
public static final int TUESDAY = 1;
public static final int WEDNESDAY = 2;
public static final int THURSDAY = 3;
public static final int FRIDAY = 4;
public static final int SATURDAY = 5;
public static final int SUNDAY = 6;
}
虽然这种方法有效,但远非理想的解决方案。视觉上太多太麻烦。
虽然这种方法有效,但远非理想的解决方案。主要是因为常量本身只是int类型的值,而代码中需要这些常量(而不是任意的int值)的每一个地方都应该被一直明确地记录和断言。从语义上来讲,比如下面的这个方法演示所表现出来的就不符合类型安全的概念:
public boolean isWeekend( int day ) {
return( day == SATURDAY || day == SUNDAY );
}
从逻辑角度去看,day参数应该是在DaysOfTheWeekConstants类中声明的值之一。然而,如果没有编写额外的说明文档(给后来的一些人阅读),就不可能猜测到这一点,所以不便于维护。当然了,对于Java编译器来说类似于isWeekend(100)的这种调用看起来完全是正确的并且不会引起任何顾虑,所以不会好心提醒你。
此时枚举就能解决这些问题。枚举允许用类型化的值替换常量并在任何地方使用这些类型。让我们使用枚举重写上面的方案。
public enum DaysOfTheWeek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
这里将关键字class改成了enum并且这些可能的值在枚举定义时被列举出来。有区别的一部分就是被声明在枚举类(在我们的例子中是DaysOfTheWeek )中的每一个单独的值都是一个实例。因此,每当枚举被使用,Java编译器都能够进行类型检查。比如:
public boolean isWeekend(DaysOfTheWeek day) {
return(day == SATURDAY || day == SUNDAY);
}
请注意枚举中的大写命名法的使用是一个约定,但是如果你不这样做也没有谁能够阻止你,但是最好还是遵守约定,这样更有利于代码的维护。
三、枚举与实例字段(Enums and instance fields)
枚举是一个特殊的类,所以它是可拓展的,所以他们可以有实例字段、构造器和方法
(特殊的是:默认无参构造器不能够被声明并且所有的构造器必须被private修饰!!!)。
(特殊的是:默认无参构造器不能够被声明并且所有的构造器必须被private修饰!!!)。
(特殊的是:默认无参构造器不能够被声明并且所有的构造器必须被private修饰!!!)。
让我们使用枚举的实例和构造器添加一个isWeekend属性。
public enum DaysOfTheWeekFields {
MONDAY(false),
TUESDAY(false),
WEDNESDAY(false),
THURSDAY(false),
FRIDAY(false),
SATURDAY(true),
SUNDAY(true);
private final boolean isWeekend;
private DaysOfTheWeekFields( final boolean isWeekend ) {
this.isWeekend = isWeekend;
}
public boolean isWeekend() {
return isWeekend;
}
}
如上述代码中我们看到的,枚举值只是简单的调用了构造器而并没有要求使用new关键字。isWeekend()方法可以用来确定是否枚举值代表工作日或者周末(即是否生效)。如下:
public boolean isWeekend( DaysOfTheWeek day ) {
return day.isWeekend();
}
四、枚举与接口(Enums and interfaces)
另外一个强大的特性,我们可以通过实现接口,再次确认了一下枚举确实是一个特殊的类,因为它能够实现接口(然而枚举不能够继承任何类,第“五”节讲)。比如,让我们引入接口DayOfWeek。
interface DayOfWeek {
boolean isWeekend();
}
然后合并实例字段和接口实现的枚举例子如下:
public enum DaysOfTheWeekFieldsInterfaces implements DayOfWeek {
MONDAY( false ),
TUESDAY( false ),
WEDNESDAY( false ),
THURSDAY( false ),
FRIDAY( false ),
SATURDAY( true ),
SUNDAY( true );
private final boolean isWeekend;
private DaysOfTheWeekFieldsInterfaces(final boolean isWeekend){
this.isWeekend = isWeekend;
}
@Override
public boolean isWeekend() {
return isWeekend;
}
}
五、枚举与泛型
在Java中,虽然咋一看并看不出来枚举和泛型的关系,但是他们之间存在一种关系。Java中的每一个单独的枚举自动继承自泛型类Enum<T>,在这里T就是枚举类型本身。Java编译器在编译时帮忙替代开发者做了这个转换,拓展一下枚举声明public enum DaysOfTheWeek 如下:
public class DaysOfTheWeek extends Enum< DaysOfTheWeek > {
// Other declarations here
}
这也就说明了为什么枚举可以实现接口但不能继承其他类:因为它隐式的继承自Enum<T>并且我们在使用对象的公共方法时已经讨论过,Java中不支持多继承。
节选自:https://blog.csdn.net/zyhlwzy/article/details/79045066,不常用的部分就没复制过来,感兴趣的可以去原博客看看。