Java在1.5之后,有了enum关键字,定义枚举类。它是一种特殊的类,同样可以有方法和属性,可以实现一个或多个接口,可以定义构造器。它与普通类区别:
1.枚举类可实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是Object类。而java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。
2.枚举类的构造器只能使用private访问控制符,省略则默认为private,指定也只能指定private。
3.枚举类的所有实例必须在枚举类中显式列出。系统自动添加public static final修饰符。
4.所有枚举类都提供了一个values方法,方便遍历所有的枚举值。
使用enum关键字创建EnumSeason,如下:
2 | SPRING, SUMMER, FALL, WINTER |
替代使用String定义常量:
1 | public class EnumSeason { |
2 | public static final String SPRING = “SPRING”; |
3 | public static final String SUMMER = “SUMMER”; |
4 | public static final String FALL = “FALL”; |
5 | public static final String WINTER = “WINTER”; |
由于使用字符串常量这种方式是编译时常量,即在.java文件在编译成.class时,会把这些常量替换为相应的值。这样其他的类里有引用到的时候也会被替换,如果字符串常量发生改变了,那么其他的类也要重新进行编译。而枚举是运行时,枚举类改变后,只需要重新编译枚举类即可。
使用枚举类:
01 | public static void main(String[] args) { |
02 | judge(EnumSeason.SPRING); |
03 | for (EnumSeason s : EnumSeason.values()) { |
04 | System.out.println(s.ordinal() + ":" + s); |
07 | public static void judge(EnumSeason season) { |
10 | System.out.println( "春暖花开" ); |
13 | System.out.println( "夏日温情" ); |
16 | System.out.println( "秋高气爽" ); |
19 | System.out.println( "东风瑟瑟" ); |
21 | System.out.println( "什么呀这是" ); |
|
运行结果如下:
春暖花开 0:SPRING 1:SUMMER 2:FALL 3:WINTER |
为枚举类添加属性,如下:
使用如下:
1 | Gender g = Enum.valueOf(Gender. class , "FEMALE" ); |
3 | System.out.println(g + "代表:" + g.name); |
Enum类的静态方法valueOf(Class, String)
上面直接访问enum属性的方式不太安全,可以改为添加setter/getter方法:
05 | public String getName() { |
09 | public void setName(String name) { |
15 | System.out.println( "参数错误" ); |
23 | System.out.println( "参数错误" ); |
主函数如下:
1 | Gender g = Enum.valueOf(Gender. class , "FEMALE" ); |
3 | System.out.println(g + "代表:" + g.getName()); |
6 | System.out.println(g + "代表:" + g.getName()); |
这种方法仍不够科学,因为枚举类通常设计成不可变类,即属性值不允许修改,这样更安全,因此应该把枚举类的属性都使用private final修饰。可使用private构造函数方式,如下:
3 | private final String name; |
5 | private Gender(String name) { |
Enum枚举实现接口,例子如下:因为有了构造函数,因此枚举变量中每个值都得使用构造函数方式,因此MALE("男")没有问题,而FEMALE就编译通不过,因为没有无参的构造函数。
01 | interface InterfaceForEnum { |
05 | enum EmotionEnum implements InterfaceForEnum{ |
10 | System.out.println( "I'm an emotion" ); |
这种方式,每个枚举值调用fun()方法时,行为就一样了,没能达到接口效果,可改为如下:
01 | enum EmotionEnum implements InterfaceForEnum{ |
04 | System.out.println( "I'm very happy" ); |
11 | System.out.println( "I'm angry" ); |
同样,也可以在enum中定义抽象方法,这样每个枚举值都得实现该抽象方法。
03 | public int evel( int n1, int n2) { |
09 | public int evel( int n1, int n2) { |
14 | public abstract int evel( int n1, int n2); |
同时,使用枚举实现单例模式,可以实现单例模式,并且可以防止通过反射和序列化方式破解单例
1 | public enum Singleton { |
4 | public void method1() { |
5 | System.out.println( "hello" ); |