Это в порядке для использования == на перечислениях в Java?

Это действительно не связано с CRTP, а скорее с тем фактом, что для зависимого от базового доступа производного кода вам нужно квалифицировать вещи.

Изменение строки на

std::cout<protectedData<

разрешило ее.

См. , обращаясь к члену базового класса в производном классе .

105
задан Kip 10 February 2009 в 19:59
поделиться

7 ответов

Просто мои 2 цента: Вот код для Enum.java, как опубликовано Sun и частью JDK:

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {

    // [...]

    /**
     * Returns true if the specified object is equal to this
     * enum constant.
     *
     * @param other the object to be compared for equality with this object.
     * @return  true if the specified object is equal to this
     *          enum constant.
     */
    public final boolean equals(Object other) { 
        return this==other;
    }


}
145
ответ дан Varkhan 5 November 2019 в 10:54
поделиться

Да, это - как будто Вы создали одноэлементные экземпляры для каждого значения в перечислении:

public abstract class RoundingMode {
  public static final RoundingMode HALF_UP = new RoundingMode();
  public static final RoundingMode HALF_EVEN = new RoundingMode();

  private RoundingMode() {
    // private scope prevents any subtypes outside of this class
  }
}

Однако , эти enum конструкция приносит Вам различную пользу:

  • toString Каждого экземпляра () печатает имя, данное в коде.
  • (Как упомянуто в другом сообщении) переменная перечислимого типа может быть сравнена с константами с помощью switch-case управляющая структура.
  • Все значения в перечислении могут быть запрошены с помощью values поле, которое 'сгенерировано' для каждого перечислимого типа
  • , Вот является большой w.r.t сравнениями идентификационных данных: перечислимые значения переживают сериализацию без клонирования.

сериализация является большим gotchya. Если бы я должен был использовать код выше вместо перечисления, вот то, как равенство идентификационных данных вело бы себя:

RoundingMode original = RoundingMode.HALF_UP;
assert (RoundingMode.HALF_UP == original); // passes

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(original);
oos.flush();

ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
RoundingMode deserialized = (RoundingMode) ois.readObject();

assert (RoundingMode.HALF_UP == deserialized); // fails
assert (RoundingMode.HALF_EVEN == deserialized); // fails

Вы можете решать эту проблему без перечисления, с помощью техники, которая включает writeReplace и readResolve, (см. http://java.sun.com/j2se/1.4.2/docs/api/java/io/Serializable.html )...

я предполагаю, что точка - Java старается изо всех сил позволять Вам, используют идентификационные данные перечислимых значений для тестирования равенства; это - поощренная практика.

13
ответ дан Dilum Ranatunga 5 November 2019 в 10:54
поделиться

Да, == прекрасен - там, как гарантируют, будет просто единственной ссылкой для каждого значения.

Однако существует лучший способ записать Ваш круглый метод:

public int round(RoundingMode roundingMode) {
  switch (roundingMode) {
    case HALF_UP:
       //do something
       break;
    case HALF_EVEN:
       //do something
       break;
    // etc
  }
}

даже лучше способ сделать это должно поместить функциональность в самом перечислении, таким образом, Вы могли просто звонить roundingMode.round(someValue). Это добирается до сути перечислений Java - они объектно-ориентированы перечисления, в отличие от "именованных значений", найденных в другом месте.

РЕДАКТИРОВАНИЕ: спецификация не очень ясна, но раздел 8.9 состояния:

ножка перечислимой литеры может содержать перечислимые константы. Перечислимая константа определяет экземпляр перечислимого типа. Перечислимый тип не имеет никаких экземпляров кроме определенных его перечислимыми константами.

76
ответ дан Jon Skeet 5 November 2019 в 10:54
поделиться

Вот некоторый злой код, который Вы могли бы найти интересным. :D

public enum YesNo {YES, NO}

public static void main(String... args) throws Exception {
    Field field = Unsafe.class.getDeclaredField("theUnsafe");
    field.setAccessible(true);
    Unsafe unsafe = (Unsafe) field.get(null);
    YesNo yesNo = (YesNo) unsafe.allocateInstance(YesNo.class);

    Field name = Enum.class.getDeclaredField("name");
    name.setAccessible(true);
    name.set(yesNo, "YES");

    Field ordinal = Enum.class.getDeclaredField("ordinal");
    ordinal.setAccessible(true);
    ordinal.set(yesNo, 0);

    System.out.println("yesNo " + yesNo);
    System.out.println("YesNo.YES.name().equals(yesNo.name()) "+YesNo.YES.name().equals(yesNo.name()));
    System.out.println("YesNo.YES.ordinal() == yesNo.ordinal() "+(YesNo.YES.ordinal() == yesNo.ordinal()));
    System.out.println("YesNo.YES.equals(yesNo) "+YesNo.YES.equals(yesNo));
    System.out.println("YesNo.YES == yesNo " + (YesNo.YES == yesNo));
}
6
ответ дан Peter Lawrey 5 November 2019 в 10:54
поделиться

== сравнивает ссылки двух объектов. Для перечислений гарантируется, что только будет один экземпляр, и поэтому для любых двух перечислений, которые являются тем же, == будет верно.

Ссылка:

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

(ничего не мог найти в документах солнца)

10
ответ дан levand 5 November 2019 в 10:54
поделиться

Перечисления являются великолепным местом для затора полиморфного кода.

enum Rounding {
  ROUND_UP {
    public int round(double n) { ...; }
  },
  ROUND_DOWN {
    public int round(double n) { ...; }
  };

  public abstract int round(double n);
}

int foo(Rounding roundMethod) {
  return roundMethod.round(someCalculation());
}

int bar() {
  return foo(Rounding.ROUND_UP);
}
3
ответ дан paulmurray 5 November 2019 в 10:54
поделиться

Обратите внимание, что при передаче перечисления через RMI / IIOP возникает проблема. См. Эту ветку:

http://www.velocityreviews.com/forums/t390342-enum-equality.html

1
ответ дан 24 November 2019 в 03:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: