阅读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);
的方式实现
所以,如果他们真的是静态的,为什么我们可以从a
访问它们?
最后一行是我熟悉的方式。
答案 0 :(得分:5)
虽然这有效,但不要这样做。使用包含Animal.DOG
,Animal.CAT
等的枚举
以上所做的是声明枚举类型的对象,并在其上引用静态DOG
。编译器知道a
的类型,并知道您想要Animal.DOG
。但这会损害可读性。
我认为这样做的目的是缩短枚举的用法。 a.DOG
代替Animal.DOG
。如果您真的想缩短它,可以使用import static fqn.of.Animal
,然后只使用DOG
。
答案 1 :(得分:3)
撰写a.DOG
与撰写Animal.DOG
相同。也就是说,编译器将使用其编译时类型Animal替换该变量。它被认为是错误的代码,因为它隐藏了它依赖于编译时类型而不是动态类型a
的事实。
答案 2 :(得分:1)
你可以从一个实例访问静态,但它真的很糟糕,因为静态不像绑定到类的实例那么多。
无论这本书怎么说,都不要那样使用静力学。如果你运行checkstyle等,他们也会警告:)
在您的示例中,BTW a为空。是否在某处初始化了?
修改强>
我知道编译器知道a.DOG绑定的内容,因为无法覆盖静态。它不需要 a 来确定调用,只需要它具有的 a 的编译时类型。
我也知道即使 a 是 null ,我也知道该示例有效(我试过,我知道:)。
但我仍然觉得你可以从 null 获取东西很奇怪。而且令人困惑:
Animals a = null;
System.out.println(a.DOG); // OK
a.doSomething(); // NullPointerException
当我调试NPE时,我会认为 a 不能为空,因为 println 工作正常。混乱。
啊,好吧,Java。如果你认为你已经看到它了,你又得到了别的东西:)