Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。

enum的特点

  • 在 Java 中使用 enum 关键字来定义枚举类,其地位与 class、interface 相同;
  • 枚举类和普通的类一样,可以有自己的成员变量、成员方法、构造器 (只能使用 private 访问修饰符,所以无法从外部调用构造器,构造器只在构造枚举值时被调用);
  • 使用 enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Seriablizable 和 java.lang.Comparable 两个接口;
  • 枚举类的所有枚举值必须在枚举类的第一行显式地列出。系统会自动添加 public static final 修饰,无需显式添加;
    枚举值是一个定义好的枚举类的实例.
  • 非抽象的枚举类不能再派生子类。

    1. 基本用法:

    Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。 ```java enum Color { RED, GREEN, BLUE; }

public class MyClass { public static void main(String[] args) { Color myVar = Color.BLUE;

  1. switch(myVar) {
  2. case RED:
  3. System.out.println("红色");
  4. break;
  5. case GREEN:
  6. System.out.println("绿色");
  7. break;
  8. case BLUE:
  9. System.out.println("蓝色");
  10. break;
  11. }

} }

  1. <a name="PX863"></a>
  2. ### 2. 高级用法:
  3. 枚举跟普通类一样可以用自己的变量、方法和构造函数,**构造函数只能使用 private 访问修饰符**,所以外部无法调用。
  4. <a name="LCdlh"></a>
  5. #### A. 枚举类的成员变量、成员方法、构造器
  6. ```java
  7. enum Color
  8. {
  9. RED("红色"), GREEN("绿色"), BLUE("蓝色");
  10. //成员属性
  11. private String color;
  12. // 构造函数
  13. private Color()
  14. {
  15. System.out.println("Constructor called for : " + this.toString());
  16. }
  17. // 成员方法
  18. public void colorInfo()
  19. {
  20. System.out.println("Universal Color");
  21. }
  22. //getter and setter
  23. public String getColor(){
  24. return color;
  25. }
  26. public void setColor(String color){
  27. this.color = color;
  28. }
  29. }
  30. public class Test
  31. {
  32. // 输出
  33. public static void main(String[] args)
  34. {
  35. Color c1 = Color.RED;
  36. System.out.println(c1); //结果为 "RED"
  37. c1.colorInfo(); //结果为 "Universal Color"
  38. System.out.println(c1.getColor()); //结果为"红色"
  39. }
  40. }

B. 枚举类中的常用方法

  • int ordinal(): 返回枚举值在枚举类中的索引值(从0开始),即枚举值在枚举声明中的顺序,这个顺序根据枚举值声明的顺序而定;
  • int compareTo(E o) and boolean equals(E o): 根据索引值进行比较;
  • static values(): 返回一个包含全部枚举值的数组,可以用来遍历所有枚举值;
  • String name(): 返回即枚举值的名称 ;
  • String toString(): 返回枚举值的名称,与 name 方法类似,更常用;

    1. // 定义一个星期的枚举类
    2. public enum WeekEnum {
    3. // 因为已经定义了带参数的构造器,所以在列出枚举值时必须传入对应的参数
    4. SUNDAY("星期日"), MONDAY("星期一"), TUESDAY("星期二"), WEDNESDAY("星期三"),
    5. THURSDAY("星期四"), FRIDAY("星期五"), SATURDAY("星期六");
    6. // 定义一个 private 修饰的实例变量
    7. private String date;
    8. // 定义一个带参数的构造器,枚举类的构造器只能使用 private 修饰
    9. private WeekEnum(String date) {
    10. this.date = date;
    11. }
    12. // 定义 get set 方法
    13. public String getDate() {
    14. return date;
    15. }
    16. public void setDate(String date) {
    17. this.date = date;
    18. }
    19. // 重写 toString() 方法
    20. @Override
    21. public String toString(){
    22. return date;
    23. }
    24. }

    ```java for (WeekEnum we : WeekEnum.values()) { System.out.print(we.name() +”, “); } 运行结果: SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY,

// 重写了 toString 方法 for (WeekEnum we : WeekEnum.values()) { System.out.print(we + “, “); } 运行结果: 星期日, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六,

  1. <a name="X9bue"></a>
  2. #### C. 枚举类实现接口
  3. 与普通类一样,枚举类也可以实现一个或多个接口。枚举类实现接口时,同样要实现<br />该接口的所有方法。
  4. ```java
  5. interface GenderDescription {
  6. void info();
  7. }
  8. enum Gender implements GenderDescription {
  9. MALE, FEMALE;
  10. @Override
  11. public void info() {
  12. System.out.println("这是一个用于定义性别的枚举类");
  13. }
  14. }
  15. public class Test02 {
  16. public static void main(String[] args) {
  17. Gender.MALE.info();
  18. Gender.FEMALE.info();
  19. }
  20. }

D. 包含抽象方法的枚举类

枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。
定义一个 Operation 枚举类,有4个枚举值PLUS、MINUS、TIMES、DIVIDE,分别代表加、减、乘、除,该枚举类有一个 calculate() 方法,用于完成计算。

  1. public enum Operation {
  2. // 用于执行加法运算
  3. PLUS { // 花括号部分其实是一个匿名内部子类
  4. @Override
  5. public double calculate(double x, double y) {
  6. return x + y;
  7. }
  8. },
  9. // 用于执行减法运算
  10. MINUS { // 花括号部分其实是一个匿名内部子类
  11. @Override
  12. public double calculate(double x, double y) {
  13. // TODO Auto-generated method stub
  14. return x - y;
  15. }
  16. },
  17. // 用于执行乘法运算
  18. TIMES { // 花括号部分其实是一个匿名内部子类
  19. @Override
  20. public double calculate(double x, double y) {
  21. return x * y;
  22. }
  23. },
  24. // 用于执行除法运算
  25. DIVIDE { // 花括号部分其实是一个匿名内部子类
  26. @Override
  27. public double calculate(double x, double y) {
  28. return x / y;
  29. }
  30. };
  31. //为该枚举类定义一个抽象方法,枚举类中所有的枚举值都必须实现这个方法
  32. public abstract double calculate(double x, double y);
  33. }
  34. public class Test03 {
  35. public static void main(String[] args) {
  36. System.out.println("6 + 2 = " + Operation.PLUS.calculate(6, 3));
  37. System.out.println("6 - 2 = " + Operation.MINUS.calculate(6, 2));
  38. System.out.println("6 * 2 = " + Operation.TIMES.calculate(6, 2));
  39. System.out.println("6 / 2 = " + Operation.DIVIDE.calculate(6, 2));
  40. }
  41. }

3. 使用enum写SIngleton:

  1. public enum SingleTon {
  2. INSTANCE;
  3. public void method() {
  4. System.out.println("我很牛逼!");
  5. }
  6. }

不比不知道,一比吓一跳啊!枚举方式的单例简单到爆——为了不至于看起来太过精简,我还加了一个输出“我很快乐”的方法。
枚举实现的单例可轻松地解决两个问题:
①、线程安全问题。因为Java虚拟机在加载枚举类的时候,会使用ClassLoader的loadClass方法,这个方法使用了同步代码块来保证线程安全。
②、避免反序列化破坏单例。因为枚举的反序列化并不通过反射实现。