枚举作为实例变量

Luc*_*uke 19 java enums scjp

如果你有一个枚举如

enum Coffee {
    BIG,
    SMALL
}
Run Code Online (Sandbox Code Playgroud)

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

public class MyClass {
    private Coffee coffee;

    // Constructor etc.
}
Run Code Online (Sandbox Code Playgroud)

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

Psh*_*emo 20

enum Coffee {
    BIG,
    SMALL
}
Run Code Online (Sandbox Code Playgroud)

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

Coffee b1 = Coffee.BIG;
Run Code Online (Sandbox Code Playgroud)

或者类似于类的引用

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

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


Aja*_*rge 13

这是幕后发生的事情:

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 {};
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样BIG,SMALL枚举中基本上是静态字段.

JLS也使这部分明确:

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

希望这能澄清你的问题.


01e*_*1es 5

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

从Java 5开始,enum构造实际上是一个做同样事情的糖,并且不允许处理像null值这样的事情,枚举值变成公共静态字段等.