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

Posted kuluo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了若没有任何实例包含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, "u7ea2u8272");
    public static final /* enum */ Color1 GREEN = new Color1("GREEN", 1, "u7effu8272");
    public static final /* enum */ Color1 BLUE = new Color1("BLUE", 2, "u84ddu8272");
    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

以上是关于若没有任何实例包含Class Body 则enum被隐式声明为final的主要内容,如果未能解决你的问题,请参考以下文章

C# Enum,Int,String的互相转换 枚举转换

Kotlin enum class 匿名类实例

JAVA枚举可以用来做啥?举一个简单的例子(用枚举、不用)

enum在java中是啥意思

第六章 类文件结构

java枚举类Enum方法简介(valueof,value,ordinal)