Имена enum интернированы в Java?
имена enum интернированы в Java?
т. е. гарантируется ли, что enum1.name() == enum2.name()
в случае с тем же именем? И безопасно ли сравнивать enum.name()
к строке, которая гарантированно будет интернирована.
4 ответа:
Хотя нет явной гарантии этого, конечный результат обязательно будет таким, что сравнение всегда будет успешным для
enum
константы с одинаковыми именами:enum A {enum1}; enum B {enum1}; System.out.println(A.enum1.name() == B.enum1.name()); // Prints "true"
причина этого в том, что компилятор Java создает подклассы
Enum
таким образом, что они в конечном итоге вызовEnum
единственный защищенный конструктор, передающий ему имяenum
значение:protected Enum(String name, int ordinal);
имя встраивается в сгенерированный код в виде строки буквальный. Согласно
String
документациявсе литеральные строки и строковые константные выражения интернируются.
это означает неявную гарантию успешного выполнения вашего выражения, когда имена
enum
константы идентичны. Однако я бы не стал полагаться на такое поведение, а использовалequals(...)
вместо этого, потому что любой читающий мой код будет почесывать голову, думая, что я сделал ошибку.
нет.
ответ Dasblinkenlight это лучший ответ, который мы имеем до сих пор. Там он говорит:
причина этого заключается в том, что компилятор Java создает подклассы
Enum
таким образом, что они в конечном итоге вызовEnum's
единственной защитой конструктор, передавая ему имяenum
стоимостьюи там их интернируют, потому что они строковые константы.
а, в JLS, 8.9.2, Перечисление Тела Объявления есть:
на практике, компилятор, скорее всего, зеркало
Enum
тип объявленияString
иint
параметры в конструкторе по умолчанию Анenum
тип. Однако эти параметры не указаны, как "неявно объявлено" потому что различные компиляторы не нужно согласитесь на форму конструктора по умолчанию. Только компилятор Анenum
тип знает, как создаватьenum
константы; другие компиляторы могут просто полагаться на неявно объявленныйpublic static
поля изenum
тип (§8.9.3) без учета того, как эти поля были инициализированы.(выделено мной)
поэтому мы вызовем конструктор, но мы не вынуждены делать это в той или иной путь, и мы можем управлять нашим собственным конструктором в компиляторе.
таким образом, это вполне возможно для меня, чтобы написать правильный и JLS-совместимый Java-компилятор, который не будет каким-то образом интернировать имена, вероятно, не имея имен, хранящихся в виде литералов. Да, он будет делать это нарочно, чтобы злонамеренно нарушить ваш код, но это будет правильное поведение в спецификации.
практически сказал, Да.
каждая здравая реализация будет интернировать строки. Я бы сказал, что это безопасно предположим такое поведение. Это не гарантировано, и поэтому, если я видел это в реальном коде, Я был бы очень недоволен им, даже если бы он был подробно описан в комментарии.
пожалуйста, не полагайтесь на такое неопределенное и специфичное для реализации поведение. Если вам действительно нужно, напишите для него модульный тест. И поставить
assert
в коде, и много объяснять. Измерьте, действительно ли ваш подход будет что-то делать.
рассмотрим цикл над иэто не работает надежно. Смотрите комментарии.intern()
их вручную перед их использованием. Таким образом, это будет сразу же ясно, что вы делаете.
со строками, которые вы собираетесь хотите, чтобы использовать метод Equals строк. Кроме того, у вас уже есть перечисление, которое можно сравнить с оператором равенства. При каком сценарии это произойдет?
Это, как говорится, да .метод equals возвращает true, если они одинаковы.
Я не уверен в операторе равенства, и, не глядя на него, я могу сказать вам, что это плохое Программирование, чтобы использовать его, если это так.
в документации Oracle о Enum говорится (первая строка):
тип перечисления-это специальный тип данных, который позволяет переменной быть набором предопределенных констант. переменная должна быть равна одному из заранее заданных значений для него. Общие примеры включают направления компаса (значения севера, юга, востока и Запада) и дни недели.
если это правда, то, да, ваш
enum1.name() == enum2.name()
гарантированно будет истинно, если имена те же самые.также, в методе
name()
javadoc:public final String name() Возвращает имя этой константы перечисления, точно как объявлено в ее объявлении перечисления. Большинство программистов должны использовать метод toString() вместо этого, так как метод toString может возвращать более удобное имя. Этот метод предназначен в первую очередь для использования в специализированных ситуациях, где корректность зависит от получения точного названия, которое не будет меняться от выпуска к выпуску. Возвращает: имя этой константы перечисления
например, если у вас было два перечисления,
Days
иMyDays
, где Воскресенье является общим значением, == между значениями объекта перечисления, в воскресенье будет возвращать значение true, как вы сравниваете две строки - см. в рабочем примере в http://ideone.com/U1Bmcw./* Name of the class has to be "Main" only if the class is public. */ class Ideone { public static enum Day{SUNDAY, MONDAY, TUESDAY}; public static enum MyDays{SUNDAY}; public static void main (String[] args) throws java.lang.Exception { MyDays m = Ideone.MyDays.SUNDAY; Day d = Ideone.Day.SUNDAY; System.out.println(d.name() == m.name()); } }