枚举类存在的意义
有时候,一个类的对象是有限固定的,比如季节类,就只有四个对象。这种实力有限且固定的类就是枚举类。
以前就用简单的静态常量来表示枚举,比如下面的定义季节枚举
public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER = 2;
public static final int SEASON_AUTUMN = 3;
public static final int SEASON_WINTER = 4;
这样写起来很简单,但是有几个问题。
- 类型不安全,上面的每个季节实际上是int整数,我们完全可以进行整数的运算,比如SEASON_SPRING+SEASON_SUMMER,这看起来很诡异但是程序也不会报错。
- 打印输出的意义不明确:输出某个季节时,比如SEASON_SPRING,输出的是数字1,这容易让人迷惑。
为了使用枚举,同时避免上面的弊端,Java的enum就是很好的选择。这就是enum存在的意义。
枚举简单入门
enum是一个关键字,它的地位和用法和class,interface一样。被enum修饰的类始终还是一个类,一个类可以做的事,比如定义成员变量,构造函数等枚举类也可以做。只不过Enum类有下面几个限制。
- enum定义的枚举类没有继承Object,而是继承了java.lang.Enum类,所以枚举类不能显示继承其它类。
- enum类默认使用final修饰,所以枚举类不能被继承。
- 枚举类的构造器默认使用private修饰,而且只能private不能是其它的。
- 枚举类的所有实例必须在类的第一行就明确写出,否则这个枚举类就不能有任何实例,那就失去了枚举类的意义。而且这些实例默认使用public static final修饰,而且也只能被这样修饰。
我们可以看一下枚举类的定义的写法
public enum SeasonEnum {
SPRING, SUMMER, AUTUMN, WINTER;
//定义其它的
}
这里定义了季节枚举类,第一行必须写季节类的实例,这些实例用逗号隔开,以分号结尾。处于代码规范,建议枚举类的所有实例名全用大写,这样别人一看就知道这个是枚举类实例。
定义了枚举类之后,我们获取枚举类的实例就比较简单,就像是获取一个类的成员变量一样。比如以下代码
public enum SeasonEnum {
SPRING, SUMMER, AUTUMN, WINTER;
//定义其它的
}
//直接得到SPRING实例
SeasonEnum spring = SeasonEnum.SPRING;
下面说说枚举类常用的方法。
- String name()和String toString()
这两个方法都是返回枚举实例在枚举类中名字。比如上面的季节枚举类,我们写如下代码。
SeasonEnum spring = SeasonEnum.SPRING;
System.out.println(spring.name());
System.out.println(spring.toString());
输出结果如下
书上说toString()的返回结果比name()的要人性化一些,但是看源码的话,这两者返回的结果是一样的。
- int compareTo(E o)
该方法是用于比较枚举实例在枚举类的定义中的先后顺序的。比如上面的季节类,SPRING在SUMMER之前,SUMMER在AUTUMN之前。如果被比较的枚举实例在调用者之前,则返回1;如果被比较的枚举在调用者之后,返回-1;否则返回0。
这个方法的参数必须是和调用者属于同一个枚举类,季节枚举必须和季节枚举做对比,不能和动物枚举做对比。
下面是这个方法的示例
SeasonEnum spring = SeasonEnum.SPRING;
System.out.println(spring.name());
System.out.println(spring.toString());
输出结果如下
- int ordinal()
返回枚举实例在枚举类中的索引值,第一个索引从0开始。比如上面的季节枚举类,SPRING的索引值是0,SUMMER是1。
方法的示例如下
System.out.println(SeasonEnum.SPRING.ordinal());
System.out.println(SeasonEnum.SUMMER.ordinal());
System.out.println(SeasonEnum.AUTUMN.ordinal());
System.out.println(SeasonEnum.WINTER.ordinal());
输出结果如下