【问题标题】:How does java support instance variables of java enum constants?java如何支持java枚举常量的实例变量?
【发布时间】:2014-12-07 05:01:32
【问题描述】:

我知道在 Java 中 enum 常量隐含地是 static final 变量。但是enum 类可以有一个实例变量,比如大小。所以每个enum 常量都会有一个'size'的副本。 等效的 Java 代码是什么?我的意思是它“似乎”静态enum 常量正在使用通常不可能的非静态实例变量?

enum Members{
    A(1),B(2),C(3);  // I have 3 enum constants here

    private int size;
    Members (int size) {
        //System.out.println("Initializing var with size = "+size);
    }
}

目前我知道的等效代码:

public final class Member extends Enums<Members> {
    public static final Members A;
    // ...
    // What happened to size? How do A,B,C get a copy of size?
}

编辑:重申我的问题- 我对编译器的幕后实现感兴趣。我已经知道如何使用枚举。我正在寻找编译器的功能? (例如,如果我只写 A,编译器会将其转换为“public static final Member A”。我想知道编译器如何为每个 A、B、C 提供大小的副本。

【问题讨论】:

  • 不要将变量和引用与对象混淆。

标签: java enums


【解决方案1】:

我的意思是“似乎”静态枚举常量正在使用通常不可能的非静态实例变量?

绝对有可能:enum 中的每个 static 变量本身就是一个对象,并带有其实例变量。实例是enum中的static,但它并没有使实例本身的上下文成为静态上下文。

public final class Member extends java.lang.Enums<Members> {
    public static final Members A = new Member(1) {
        public String toString() { return "A:"+size; }
    };
    public static final Members B = new Member(2) {
        public String toString() { return "B:"+size; }
    };
    public static final Members C = new Member(3) {
        public String toString() { return "C:"+size; }
    };
    private final int size;
    protected Member(int size) { this.size = size; }
}

【讨论】:

  • 为什么要为每个Member变量创建一个新类?
  • 所以你的意思是每个枚举常量 A,B,C 都得到一个大小的副本。所以java把我的代码转换成类似的东西(为A创建一个实例变量,为B等等)。这意味着编译器正在做一些幕后的事情。我一直在寻找幕后的东西。
  • 我所说的“通常”是指在非枚举类中,静态变量不能访问非静态变量。
  • @rents “这意味着编译器正在做一些幕后的事情。我一直在寻找幕后的事情。”当然,编译器在你背后做了很多事情,让你使用方便的语法。除了你在泛型、嵌套类、自动装箱和enums 中编写的内容之外,还有很多事情要做。
  • @rents “在非枚举类中,静态变量不能访问非静态变量。”您可能的意思是“静态方法不能访问非静态变量”,对吧?这就是诀窍:变量ABC 是静态的,但这些变量中的每一个都指向一个一流的对象,该对象具有实例变量,可以具有实例方法,等等。
【解决方案2】:

我的意思是“似乎”静态枚举常量正在使用通常不可能的非静态实例变量?

我所说的“通常”是指在非枚举类中,静态变量不能访问非静态变量

仍然是这样:静态变量不能访问非静态变量。 在您的示例代码中,您不要这样做: 没有静态变量访问非静态变量。

构造函数Members(int size) 不在静态上下文中(构造函数从不在)。 A、B 和 C 都是枚举类型Members 的实例, 当这些实例被创建时, 使用size 参数调用构造函数。 构造完成后,这些对象将被视为静态常量值。

也许另一个例子可以帮助:

class Person {
    private final String name;
    Person(String name) {
        this.name = name;
    }
}
class EmployeeDatabase {
    private static final Person CEO = new Person("Jack");
}

这里的EmployeeDatabase.CEO 是一个带有非静态字段name 的静态常量对象。 这就像Members.A,一个带有非静态字段size 的静态常量对象。

我想知道编译器如何为每个 A、B、C 提供大小的副本。

与将构造函数参数传递给任何对象的方式完全相同。

您可以在docs 中阅读有关枚举的所有信息。

【讨论】:

  • 这不会编译,size 不能是最终的
  • 当然可以。它不仅可以是最终的,它应该是最终的。可变枚举将是非常弱的设计。
  • 如果您有一个未初始化的final 变量,javac 不会显示错误吗?当final 变量在ctor 中初始化时?
  • @msrd0 他正在构造函数中对其进行初始化。用final 声明的变量只能直接用声明(private final int blub = 0;)或在构造函数中初始化。
  • 我不是在找这个。我对编译器的幕后实现更感兴趣。我已经知道如何使用枚举。我正在寻找编译器的功能? (例如,如果我只写 A,编译器会将其转换为“public static final Member A”。我想知道编译器如何为每个 A、B、C 提供大小的副本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多