Имена 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()); } }