《疯狂Java讲义》(十六)---- 枚举类
Posted coder为
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《疯狂Java讲义》(十六)---- 枚举类相关的知识,希望对你有一定的参考价值。
- 枚举类与普通类的区别
- 枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承java.lang.Enum类,而不是java.lang.Object类,其中java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。
- 使用enum定义,非抽象的枚举类默认会使用final修饰,因此枚举类不能派生子类。
- 枚举类的构造器只能使用private访问控制符
- 枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无须程序员显式添加。
- 枚举类都提供了一个values方法,该方法可以很方便地遍历所有的枚举值。
enum SeasonEnum { SPRING, SUMMER, FALL, WINTER; } public class EnumTest { public void judge(SeasonEnum s) { switch (s) { case SPRING: System.out.println("Spring is comming"); break; case SUMMER: System.out.println("Summer is comming"); break; case FALL: System.out.println("Fall is comming"); break; case WINTER: System.out.println("Winter is comming"); break; default: System.out.println("not exist season"); } } public static void main(String[] args) { for (SeasonEnum s : SeasonEnum.values()) { System.out.println(s); } new EnumTest().judge(SeasonEnum.SPRING); } }
- 枚举类的Field/方法/构造函数
枚举类一样可以定义Field和方法。也可以将field访问符设置为public,直接修改值,但这样破坏了类的封装性。也可以将field访问符改为private,提供getter和setter,但是通常枚举类应该设计成不可变类。
枚举类的field值不应该允许改变,这样会更安全,而且代码也简洁。所以,枚举类的field都使用private final修饰。所以必须在构造器里为这些Field指定初始值(或载定义field时指定默认值, 在初始化块中指定初始值,但这两种情况并不常见),因此应该为枚举类显式定义带参数的构造器。一旦为枚举类显式定义了带参数的构造器,在第一行列出枚举实例时就必须对应的传入参数。
public enum Gender { MALE("nan"), FEMALE("nv"); private final String name; private Gender(String name) { this.name = name; } public String getName() { return this.name; } }
在枚举类中列出枚举值时,实际上就是调用构造器创建枚举类对象,只是这里无须使用new关键字,也无须显式调用构造器。上一个例子中列出枚举值时没有传入参数,仅仅是因为前面的枚举类包含无参数的构造器。
MALE("nan") 相当于 public static final Gender MALE = new Gender("nan");
- 实现接口的枚举类
interface GenderDesc { void info(); } public enum Gender2 implements GenderDesc{ MALE, FEMALE; @Override public void info() { // TODO Auto-generated method stub } }
如果由枚举类来实现接口里的方法,则每个枚举类在调用该方法时都有相同的行为方式。如果需要每个枚举值在调用该方法时呈现不同的行为方式,则可以让每个枚举值分别来实现该方法
interface GenderDesc { void info(); } public enum Gender2 implements GenderDesc{ MALE { @Override public void info() { // TODO Auto-generated method stub } }, FEMALE { @Override public void info() { // TODO Auto-generated method stub } }; }
上边的情况中, 当创建MALE/FAMALE枚举值,并不是直接创建Gender枚举类的实例,而是相当于创建Gender的匿名子类的实例。
编译上边程序,生成Gender.class, Gender$1.class, Gender$2.class三个文件,证明MALE和FEMALE实际上是Gender匿名子类的实例,而不是Gender类的实例。
提问:枚举类不是用final修饰了吗?怎么还能派生子类呢?
回答:并不是所有的枚举类都是用了final修饰符,非抽象的枚举类才默认是用final修饰。对于一个抽象的枚举类而言 -- 只要它包含了抽象方法,它就是抽象枚举类,系统会默认是用abstract修饰,而不是final。
- 包含抽象方法的枚举类
public enum Operation { PLUS { public double eval(double x, double y) { return x + y; } }, MINUS { public double eval(double x, double y) { return x - y; } }, TIMES { public double eval(double x, double y) { return x * y; } }, DIVIDE { public double eval(double x, double y) { return x / y; } }; public abstract double eval(double x, double y); public static void main(String[] args) { System.out.println(Operation.PLUS.eval(3, 4)); System.out.println(Operation.MINUS.eval(3, 4)); System.out.println(Operation.TIMES.eval(3, 4)); System.out.println(Operation.DIVIDE.eval(3, 4)); } }
枚举类里定义抽象方法时不能使用abstract关键字将枚举类定义成抽象类(因为系统会自动为它添加abstract),但因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则编译错误。
以上是关于《疯狂Java讲义》(十六)---- 枚举类的主要内容,如果未能解决你的问题,请参考以下文章