关于java:嵌套枚举是静态的吗?

Nested enum is static?

在阅读这个问题时,我打开编辑器,尝试一些代码示例来验证和理解它。以下是我的代码:

1
2
3
4
5
6
7
8
9
10
11
public enum EnumImpl {

    B {
        public void method() {
            System.out.println(s); //(1)non-static variable s cannot be referenced from a static context
        }
        public static int b;  //(2)Illegal static declaration in inner class
    };

    private int s;
}

但是编译上面的代码让我更加困惑。

  • 第一个错误是什么上面的问题表明B实际上属于静态类。所以在method中,它是一个静态上下文。
  • 相反,第二个错误是,这里是一个内部类——非静态嵌套类,如Java DOC所说。
  • 下面是我从JLS引用的一行,但它似乎有点混乱和模糊。

    A nested enum type is implicitly static.

  • 以下是匿名合成类b的字节码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    final class enum_type.EnumImpl$1 extends enum_type.EnumImpl {
      enum_type.EnumImpl$1(java.lang.String, int);
        Code:
          0: aload_0
          1: aload_1
          2: iload_2
          3: aconst_null
          4: invokespecial #1                  // Method enum_type/EnumImpl."<init>":(Ljava/lang/String;ILenum_type/EnumImpl$1;)V
          7: return

      public void method();
        Code:
          0: return
    }

那么B类是静态的还是非静态的?

@lew bloch似乎说的是这样的(行为与上面的枚举示例相匹配,但是如果这是真的,那么链接问题的答案在某些意义上是错误的)。

1
2
3
4
5
6
7
8
9
10
11
abstract class Cmp {    
    private int s;
    static {
        class Bclass extends Cmp {
            public void method() {
//                System.out.println(s);
            }
//            private static int b;
        }
    }
}


你对method()的声明是错误的。你在常量体中声明它。但它不会覆盖任何内容。它属于枚举体,而不是实例体。

实例子类型在枚举常量的静态初始值设定项中声明。因为上下文是静态的,所以它不能访问枚举实例变量。

枚举声明不是静态的,它是顶级的,顶级类不能是静态的。

常量体定义枚举的隐式嵌套匿名子类,并且不构成jls所指的嵌套枚举。每个常量都属于要声明的枚举的不同匿名子类型,而该子类型不是静态的。但是,子类型是在静态上下文中声明的,因此代码无法到达实例变量。

编辑:来自JLS的有用参考资料

https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html jls-8.9.1"枚举常量的可选类主体隐式定义了一个匿名类声明(§15.9.5),该声明扩展了立即封闭的枚举类型。类主体由匿名类的常规规则控制;特别是它不能包含任何构造函数。只有当这些类实体中声明的实例方法重写封闭枚举类型(§8.4.8)中的可访问方法时,才能在封闭枚举类型之外调用它们。

https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html jls-15.9.5"匿名类声明是由Java编译器从类实例创建表达式自动派生的。匿名类从不抽象(§8.1.1.1)。匿名类始终是隐式的最终类(§8.1.1.2)。匿名类始终是一个内部类(§8.1.3);它从不是静态的(§8.1.1,§8.5.1)。"