枚举变量如何工作?

2022-09-03 06:39:18

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

现在,类型的变量可以指向此类型的成员对象:Animals

Animals a1 = Animals.DOG;没关系。

但是,以下链引用如何有意义呢?

Animals a2 = a1.DOG.FISH.GOAT;(是的,看起来很疯狂,在一个棘手的Java问题中看到了这一点)

真正指向的是什么?我们如何从中引用其他成员?a1enum

例:

public class EnumTest {
    enum Animals { DOG, FISH, GOAT };

    public void test(){
        Animals a1 = Animals.DOG;
        Animals a2 = a1.DOG.FISH.GOAT; //--Strange but valid--
    }
}

答案 1

Java 中 的成员就像类的静态字段一样,因此与 .enuma1.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???
    }
}

这不仅发生在 s 上,还发生在 es 上:enumclass

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在他/她的答案中指出的那样,s最终会编译成一个具有静态字段的类,所以这不是s的问题,而是像es的问题一样。enumenumclass

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

恕我直言,通过该类型的实例引用某个类型的静态成员应该是一个坏习惯。这引起了混乱,就像你所指出的那样。


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

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

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

加法:

枚举编译为的内部结构:

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 {};
}

答案 2

反编译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 {};
}

所有类型都是动物的实例,因此您可以引用其他类型。