19

如果您有一个枚举,例如

enum Coffee {
    BIG,
    SMALL
}

和一个类,它有一个像这样的枚举实例变量:

public class MyClass {
    private Coffee coffee;

    // Constructor etc.
}

为什么可以在构造函数中说 eg coffee.BIG?我不明白你可以使用参考吗?枚举作为实例变量是否被初始化为null? 这是第一章 SCJP 书中的自测题 #4。我试图缩短代码和问题。

4

3 回答 3

21

enum Coffee {
    BIG,
    SMALL
}

BIG 或 SMALL 是public static finalCoffee 类的字段,和所有静态字段一样,它们可以通过类名访问,例如

Coffee b1 = Coffee.BIG;

或通过与类相同类型的引用,例如

Coffee s2 = b1.SMALL;
Coffee s3 = Coffee.BIG.SMALL; //BIG is reference of type Coffee so it is OK (but looks strange)

但是请记住,我们应该避免通过引用访问静态成员。这会造成混乱,因为我们并没有真正访问实例的成员而是的成员(例如,没有多态行为)。

于 2012-08-04T13:31:02.617 回答
14

这是幕后发生的事情:

E:\workspace>type Coffee.java
public enum Coffee {
    BIG,
    SMALL
}

E:\workspace>javap Coffee
Compiled from "Coffee.java"
public final class Coffee extends java.lang.Enum<Coffee> {
  public static final Coffee BIG;
  public static final Coffee SMALL;
  public static Coffee[] values();
  public static Coffee valueOf(java.lang.String);
  static {};
}

如您所见BIGSMALL本质上是枚举中的静态字段。

JLS也明确了这部分:

除了枚举类型 E 从 Enum 继承的成员之外,对于每个声明的名称为 n 的枚举常量,该枚举类型都有一个隐式声明的名为 n 的类型 E 的 public static final 字段。这些字段被认为是在与相应的枚举常量相同的顺序,在枚举类型中显式声明的任何静态字段之前。每个这样的字段都被初始化为与之对应的枚举常量。

希望这能澄清你的问题。

于 2012-08-04T13:30:11.280 回答
6

在 Java 5 之前,实现枚举的方法是创建一个类,该类具有私有构造函数和初始化为特定值的同一类的公共最终字段。

从 Java 5 开始,枚举构造实际上是一种糖,它可以做同样的事情,并且处理诸如不允许空值、枚举值成为公共静态字段等事情。

于 2012-08-04T13:02:55.277 回答