嵌套枚举是静态的?

问题描述 投票:4回答:2

[阅读this question时,我打开编辑器尝试一些代码示例进行验证和理解。以下是我的代码:

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中引用的一行,但似乎有些混乱和模糊。

    嵌套枚举类型是隐式静态的。

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

    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的类别是否是静态的?

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ lobloch似乎在说像以下内容(该行为与上面的枚举示例匹配,但是如果为真,则从某种意义上说,所链接问题的答案是错误的)。

abstract class Cmp {    
    private int s;
    static {
        class Bclass extends Cmp {
            public void method() {
//                System.out.println(s);
            }
//            private static int b;
        }
    }
}
java enums
2个回答
4
投票

您的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节)。“


0
投票

错误消息“无法从静态上下文中引用非静态变量s”令人困惑,因为问题不是s是静态的,而是在method中不可访问。如果从private中删除private int s;,则错误消息消失。

© www.soinside.com 2019 - 2024. All rights reserved.