若没有任何实例包含Class Body 则enum被隐式声明为final

本文参考

今天在Java Language Specification上偶然看到一条关于枚举的语法特点说明

An enum declaration is implicitly final unless it contains at least one enum constant that has a class body

不是很理解此处Class Body的所指,查阅了一些关于Java enum的语法介绍和stack overflow上的回答,对这句话有了一定的理解

https://stackoverflow.com/questions/9891613/why-cant-a-java-enum-be-final

不含Class Body的enum声明

public enum Color1 {
  RED("
红色"),
  GREEN("
绿色"),
  BLUE("
蓝色");

  private String description;

  Color(String description) {
    this.description = description;
  }

  public String getDescription() {
    return description;
  }
}

 

不含Class Body的反编译结果

public final class Color1 extends Enum<Color1> {
    public static final /* enum */ Color1 RED = new Color1("RED", 0, "\u7ea2\u8272");
    public static final /* enum */ Color1 GREEN = new Color1("GREEN", 1, "\u7eff\u8272");
    public static final /* enum */ Color1 BLUE = new Color1("BLUE", 2, "\u84dd\u8272");
    private String description;
    private static final /* synthetic */ Color1[] $VALUES;

    public static Color1[] values() {
        return (Color1[])$VALUES.clone();
    }

    public static Color1 valueOf(String name) {
        return Enum.valueOf(Color1.class, name);
    }

    private Color1(String string, int n, String description) {
        super(string, n);
        this.description = description;
    }

    public String getDescription() {
        return this.description;
    }

    static {
        $VALUES = new Color1[]{RED, GREEN, BLUE};
    }
}

 

 

含Class Body的enum声明

这个例子中无法体现"至少有一个实例包含Class Body"的语法特点,但是后期验证确实如此,有兴趣可以改下代码自行尝试

public enum Color2 {
  RED {
    @Override
    public String getDescription() {
      return "
红色";
    }
  },
  GREEN {
    @Override
    public String getDescription() {
      return "
绿色";
    }
  },
  BLUE {
    @Override
    public String getDescription() {
      return "
蓝色";
    }
  };

  public abstract String getDescription();
}

 

含Class Body的反编译结果

public abstract class Color2 extends Enum<Color2> {
    public static final /* enum */ Color2 RED = new /* Unavailable Anonymous Inner Class!! */;
    public static final /* enum */ Color2 GREEN = new /* Unavailable Anonymous Inner Class!! */;
    public static final /* enum */ Color2 BLUE = new /* Unavailable Anonymous Inner Class!! */;
    private static final /* synthetic */ Color2[] $VALUES;

    public static Color2[] values() {
        return (Color2[])$VALUES.clone();
    }

    public static Color2 valueOf(String name) {
        return Enum.valueOf(Color2.class, name);
    }

    private Color2(String string, int n) {
        super(string, n);
    }

    public abstract String getDescription();

    /* synthetic */ Color2(String x0, int x1, 1 x2) {
        this(x0, x1);
    }

    static {
        $VALUES = new Color2[]{RED, GREEN, BLUE};
    }
}

 

结论

enum实际上是一种特殊的class声明,enum实例(如上面代码示例中的RED、GREEN和BLUE)都被隐式地声明为public static final

当enum实例包含Class Body时,这种写法实际上生成了一个继承enum的特殊的内部类,所以enum声明不能够是final(声明为final的类无法被继承)

另外一个注意点,编译器不一定为enum声明隐式地添加public修饰符,若enum声明被包含在某个接口或类内,Java接口在编译时会自动为enum类型加上public static修饰符,而Java类在编译时会自动为 enum 类型加上static修饰符,具体可以参考这篇文章:

https://www.cnblogs.com/jingmoxukong/p/6098351.html

posted @ 2020-04-22 15:55  咕~咕咕  阅读(243)  评论(0编辑  收藏  举报