16

enum Animals { DOG, FISH, GOAT };在 Java 中考虑。

现在类型的变量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

4 回答 4

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

这不仅发生在enums 上,也发生在classes 上:

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 在他/她的回答中指出的那样,enums 最终会编译成具有静态字段的类,所以这不是enums 的问题,而是类似于classes 的问题。

在其他一些语言(例如 C#)中,不允许通过类型的实例引用类型的静态成员,但 Java 是一个例外。

恕我直言,通过类型的实例引用类型的静态成员应该是一个坏习惯。正如您所指出的,这会导致混乱。


如果您喜欢使用 Eclipse IDE,它只会给您一个警告:

静态字段 Animals.DOG 应该以静态方式访问

Eclipse 还为您提供了一些建议。其中之一是更改为使用类型来引用enum成员,另一个是删除“字段的静态修饰符”(但实际上对 s 不起作用enum)。

添加:

枚举编译为的内部结构:

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 {};
}
于 2012-12-23T14:55:22.520 回答
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 的实例,所以你可以引用其他类型。

于 2012-12-23T14:47:11.503 回答
2

您所展示的是 Java 如何处理枚举类型的结果。Animals枚举类型常量是静态引用,而不是 C 中的数字原语。由于您可以通过对象/实例引用 ( )访问类型的静态成员(在本例中Animals.DOG),因此您始终可以从任何枚举常量获取任何其他枚举常量. 这里的技巧是静态成员是对其所属类型的实例的引用。

于 2012-12-23T14:42:21.333 回答
0

enum将其元素创建为 this 的静态实例enum。在某些情况下,这些实例是 this 的子类enum

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

于 2012-12-23T14:44:34.913 回答