Java:访问枚举中的常量(枚举)

阅读SCJP书,我在第1章“自测”中发现了类似的内容:

enum Animals { DOG("woof"), CAT("meow"), FISH("burble"); String sound; Animals(String s) { sound = s; } } class TestEnum { static Animals a; public static void main(String[] args) { System.out.println(a.DOG.sound + " " + a.FISH.sound); // the following line is from me System.out.println(Animals.DOG.sound + " " + Animals.FISH.sound); } } 

注意:代码编译正常。 我不明白为什么我们可以从变量a访问DOG,CAT或FISH常量。 我认为(并且也在书中写道)DOG,FISH,CAT作为常数以类似于public static final Animals DOG = new Animals(1);的方式实现public static final Animals DOG = new Animals(1); 所以,如果他们真的是静态的,为什么我们可以从a ? 最后一行是我熟悉的方式。

编写a.DOG与编写Animal.DOG相同。 也就是说,编译器将使用其编译时类型Animal替换该变量。 它被认为是错误的代码,因为它隐藏了它依赖于编译时类型而不是动态类型的事实。

虽然这有效,但不要那样做。 使用与Animal.DOGAnimal.CAT等的枚举。

上面做的是声明枚举类型的对象,并在其上引用静态DOG 。 编译器知道a的类型,并知道你想要Animal.DOG 。 但这会杀死可读性。

我相信这样做的目的是缩短枚举的用法。 a.DOG而不是Animal.DOG 。 如果你真的想缩短它,你可以使用import static fqn.of.Animal然后简单地使用DOG

可以从一个实例访问静态,但它真的很糟糕,因为静态不像绑定到类的实例那么多。

无论这本书怎么说,都不要那样使用静力学。 如果你运行checkstyle等,他们也会警告:)

在您的示例中,BTW a为null。 它是否在某处初始化?

编辑

我知道编译器知道a.DOG绑定了什么,因为静态不能被覆盖。 它不需要确定调用,只需要它的编译时类型。

我也知道这个例子可以正常工作,即使anull (我试过,所以我知道:)。

但我仍然认为你可以从null得到东西很奇怪。 而且令人困惑:

 Animals a = null; System.out.println(a.DOG); // OK a.doSomething(); // NullPointerException 

当我调试NPE时,我会假设a不能为null,因为println工作正常。 混乱。

好吧,Java。 如果你认为你已经看到它了,你又得到了别的东西:)