Как работает переменная Enumeration? - программирование
Подтвердить что ты не робот

Как работает переменная Enumeration?

Рассмотрим 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--
    }
}
4b9b3361

Ответ 1

Члены enum в Java похожи на статические поля класса, поэтому 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 s, но также 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, наконец, скомпилируется в класс со статическими полями, поэтому это не проблема enum s, а скорее проблема с class х годов.

В некоторых других языках (например, С#) вам не разрешается ссылаться на статический член типа через экземпляр типа, но Java является исключением.

ИМХО, ссылающееся на статический член типа через экземпляр типа, должно быть плохой привычкой. Это вызывает путаницу, как вы указали.


Если вам нравится использовать Eclipse IDE, он просто даст вам предупреждение:

Статическое поле Animals.DOG должно быть доступно статическим способом

Eclipse также предлагает несколько предложений для вас. Одним из них является переход на использование типа для ссылки на элемент enum, а другой - на удаление "статического модификатора поля" (но фактически не работает на enum s).

Дополнение:

Внутренняя структура того, что компиляция перечисляет:

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

Все типы - это экземпляр Animals, поэтому вы можете ссылаться на другой тип.

Ответ 3

То, что вы продемонстрировали, является следствием того, как Java обрабатывает типы перечислений. Константы типа Enum являются статическими ссылками, а не численными примитивами, такими как C. Поскольку вы можете получить доступ к статическим членам типа (в данном случае Animals) через ссылку на объект/экземпляр (Animals.DOG), вы всегда можете перейти к любому другому enum constant из любой константы перечисления. Трюк здесь - статический член - ссылка на экземпляр типа, членом которого он является.

Ответ 4

enum создает свои элементы как статические экземпляры этого enum. В некоторых случаях эти экземпляры являются подклассами этого enum.

Конечно, вы можете обращаться к методам классов и экземплярам класса (то есть статическим) с помощью объектов.