Enumeration变量如何工作?

时间:2012-12-23 14:37:57

标签: java object enums

在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--
    }
}

4 个答案:

答案 0 :(得分:12)

Java中enum的成员就像一个类的静态字段,因此a1.DOGAnimals.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的子类。

当然,您可以使用对象访问类方法和类实例(即静态)。