Почему две константы перечисления могут использоваться в одной строке? - PullRequest
0 голосов
/ 12 мая 2018

Я создал один класс Enum:

public enum Currency {

    PENNY(1), NICKLE(5), DIME(10), QUARTER(25);

    private int value;

    private Currency(int value) {
        this.value = value;
    }

};

Я пытаюсь использовать его в методе main ():

System.out.println(Currency.NICKLE.DIME.PENNY.QUARTER);
System.out.println(Currency.PENNY.QUARTER);

Нет ошибки, генерируемой этим. Он печатает константу, которая является последней.

Может кто-нибудь объяснить это?

1 Ответ

0 голосов
/ 12 мая 2018

Я постараюсь добавить немного больше к тому, что было сказано в комментариях выше.

Значения перечисления несколько особенные.Из записи Wikipedia по перечислениям Java:

Тип перечисления в Java на самом деле представляет собой специальный класс, сгенерированный компилятором, а не арифметический тип, а значения перечисления ведут себя как глобальныесгенерированные экземпляры этого класса.Типы enum могут иметь методы экземпляра и конструктор (аргументы которого можно указывать отдельно для каждого значения enum).

Таким образом, в то время как они генерируются только один раз во время компиляции, они являются специальными экземплярами заданного типа перечисления.Как таковой, он имеет доступ к другим членам класса.Обратите внимание, что это также подразумевает, что вы не можете создать экземпляр типа enum самостоятельно (то есть, используя new).

Из одного экземпляра класса enum вы можете получить доступ к другому экземпляру того же класса enum?Что я не видел в обычном классе Java.

Это также возможно в обычном классе, хотя его осуждают, так как он не дает никаких реальных преимуществ и может даже вызвать проблемы и ошибки (до NullPointerExceptions).

Рассмотрим следующие два класса:

public class SomeClass
{
  public final static int MODE = 1;
  private String message;

  public SomeClass(String message)
  {
    this.message = message;
  }
}

public class Test
{
  public static void main(String[] args)
  {
    SomeClass myObject = new SomeClass("bla");
    System.out.println(myObject.MODE);
    System.out.println(OtherClass.MODE);
  }
}

Это будет просто распечатать:

1
1

Однако представьте, что вы выполняете какое-то задание, в котором выитерация по списку SomeClass объектов, где некоторые из записей потенциально null (возможно, потому что они были удалены из коллекции в какой-то момент или потому что null записи были разрешены во время вставки по любой причине).

В этом случае, если вы получите доступ к члену static через экземпляр, вы получите NPE, тогда как доступ к нему через сам класс будет работать как положено.

Обратите внимание, что поведението, что описано в вопросе, относится только к самим типам enum (т. е. Currency.NICKLE.DIME...).Есть способ имитировать такого поведения, как показано ниже:

public class SomeClass
{
  public static SomeClass REF; // not final anymore since 'this' must be the first line in a constructor call
  public String message; // note this is public now

  public SomeClass(String message)
  {
    this.message = message;
  }

  public void setRef() {
    REF = this;
  }
}

public class Test
{
  public static void main(String[] args)
  {
    SomeClass myObject = new SomeClass("bla!");
    System.out.println(myObject.REF);
    System.out.println(SomeClass.REF);
    myObject.setRef();
    System.out.println(SomeClass.REF);
    System.out.println(SomeClass.REF.message);
  }
}

Это вывело бы:

null
null
SomeClass@...  // Object.toString() call
bla!

Но выиграть от этой выгоды абсолютно нет.используя такую ​​ужасную технику и массу недостатков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...