在Java中考虑enum Animals { DOG, FISH, GOAT };
。
现在,Animals
类型的变量可以指向此类型的成员对象:
Animals a1 = Animals.DOG;
没关系。
但以下链引用如何有意义?
Animals a2 = a1.DOG.FISH.GOAT;
(是的,看起来很疯狂,在棘手的Java问题中看到这一点)
a1
真正指向什么?我们如何引用其他enum
成员?
示例:
public class EnumTest {
enum Animals { DOG, FISH, GOAT };
public void test(){
Animals a1 = Animals.DOG;
Animals a2 = a1.DOG.FISH.GOAT; //--Strange but valid--
}
}
答案 0 :(得分:12)
Java中enum
的成员就像一个类的静态字段,因此a1.DOG
与Animals.DOG
完全相同。
public class EnumTest {
enum Animals { DOG, FISH, GOAT };
public void test(){
Animals a1 = Animals.DOG;
Animals a2 = a1.DOG; // the same as Animals.DOG, but makes code messy
Animals a3 = a1.DOG.FISH; // WTF chaining???
}
}
这不仅发生在enum
上,还发生在class
es:
public class A {
public static A a_1;
public static A a_2;
public void boo() {
A a = A.a_1;
A b = a.a_1; // That makes a equal to b!
A c = a.a_1.a_2; // I HATE "CHAINING" LIKE THIS
}
}
就像@lichengwu在他/她的回答中指出的那样,enum
s最终会编译成一个带有静态字段的类,所以这不是enum
的问题,而是像问题class
es。
在其他一些语言(例如C#)中,不允许通过类型的实例引用类型的静态成员,但Java是一个例外。
IMHO通过该类型的实例引用类型的静态成员应该是一个坏习惯。这会引起你所指出的混乱。
如果您喜欢使用Eclipse IDE,它只会给您一个警告:
应以静态方式访问静态字段Animals.DOG
Eclipse还为您提供了一些建议。其中之一是更改为使用类型引用enum
成员,另一个是删除“字段的静态修饰符”(但实际上不适用于enum
)。
<强>增加:强>
Enumeration编译的内部结构:
final class Animals extends java.lang.Enum<Animals> {
public static final Animals DOG;
public static final Animals FISH;
public static final Animals GOAT;
public static Animals[] values();
public static Animals valueOf(java.lang.String);
static {};
}
答案 1 :(得分:5)
反编译Animals.class
javap Animals.class
:
final class Animals extends java.lang.Enum<Animals> {
public static final Animals DOG;
public static final Animals FISH;
public static final Animals GOAT;
public static Animals[] values();
public static Animals valueOf(java.lang.String);
static {};
}
所有类型都是Animals的实例,因此您可以引用其他类型。
答案 2 :(得分:2)
您所演示的是Java处理枚举类型的结果。枚举类型常量是静态引用,而不是C中的数字原语。由于您可以通过对象/实例引用(Animals
)访问类型的静态成员(在本例中为Animals.DOG
),您始终可以从任何枚举常量中获取任何其他枚举常量。这里的技巧是静态成员是对其所属类型的实例的引用。
答案 3 :(得分:0)
enum
将其元素创建为此enum
的静态实例。在某些情况下,这些实例是此enum
的子类。
当然,您可以使用对象访问类方法和类实例(即静态)。