enum.values ​​() - це порядок повернених enums детермінованим


105

У мене є перерахунок SOME_ENUM :

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

Будемо SOME_ENUM.values()завжди повертати перерахування в порядку декларацій перерахувань: EN_ONE, EN_TWO, EN_THREE? Це правило чи це не гарантується, що воно не буде змінено в наступних випусках JDK?


1
Я повторюю свій перелік, щоб заповнити список, який, ніж інше місце в коді, я читав ітерацію над цим перерахунком.
Скараб

11
@MitchWheat З тієї ж причини, що ви покладаєтесь на порядок збереження списку: тому що JDK - це інструмент, який дає певні гарантії і покладаючись на ці гарантії, допомагає вам написати більш короткий та кращий код. Справді, питання "Чи гарантовано його не змінити?" відповісти неможливо, ти точно не можеш покластися на це, нічого не має на те гарантії.
Флетч

Відповіді:


144

Специфікація мови Java використовує цю явну мову:

@return масив, що містить константи цього типу перерахунку, у порядку, який вони оголосили [Джерело]

Отже, так, вони будуть повернуті в порядку декларації. Варто зазначити, що замовлення може змінитися з часом, якщо хтось змінить клас, тому будьте дуже обережні, як ви цим користуєтеся.


1
Якщо хтось додасть значення в середині в більш пізній версії коду, це може спричинити вам шланг, оскільки це змінить порядкове значення інших елементів (див. Метод Enum.ordinal ()). З цієї причини краще не покладатися на порядкове положення як механізм серіалізації (тобто не зберігати його в db).
Мет

1
Посилання на джерело для цієї специфікації?
Дан Гран


16

Так, гарантовано повернути їх у такому порядку.

Однак вам слід уникати покладання на це та на ordinal()значення, оскільки воно може змінюватися після вставки нових елементів, наприклад.


+1 за порадою мудреця. На тему ordinal (), Ефективна Java пропонує додати поле члена до типу enum.
іде

9

Це визначається порядком, за яким оголошуються ваші значення. Однак немає гарантії, що ви (чи хтось інший) не будете впорядкувати / вставляти / видаляти значення в майбутньому . Тож не варто покладатися на замовлення.

Ефективна Java 2-а. Видання присвячує свій Пункт 31 тісно пов'язаній темі: Використовуйте поля екземплярів замість порядкових знаків :

Ніколи не виводьте значення, пов'язане з перерахунком, від його порядкових значень; зберігайте його в полі екземпляра.


3
"немає гарантії, що хтось не змінить значення в майбутньому" - але саме тому я хочу покластися на замовлення :-)! Я хочу мати можливість впорядкувати замовлення в майбутньому і тим самим змінити поведінку моєї програми. Блох має рацію в тому, що не покладатися на порядковий порядок, і якщо приклад запитувача насправді передбачає перерахунки на зразок EN_TWO, то він покладається на порядковий і не повинен цього робити. Але покладатися на замовлення - це абсолютно чудово. Насправді, оскільки замовлення гарантовано, для створення спеціального поля для замовлення буде писати надлишковий код, такі речі, як «Ефективна Java», говорять вам не робити.
Флетч

@Fletch, вибач, я не дуже стежу за тобою. Для мене це звучить так, ніби ви намагаєтесь використовувати enumдля тих цілей, які не були призначені.
Петер Тьорьк

скажімо, у вас є відомий перелік "Планети". У своєму інтерфейсі ви хочете перерахувати планети в порядку їх відстані від сонця. Як можна найкраще це досягти? Я замовив би константи планети в правильному порядку всередині класу enum, а потім просто перерахував enum в інтерфейсі користувача. Оскільки замовлення є надійним, це працюватиме. Про таку річ, про яку я говорю. Якщо одного дня Земля просунеться ближче до Сонця, ніж Марс, звичайно, в таку хвилину першим, що у вас на душі, буде підтримка вашого коду! Таким чином, ви переходите до свого класу Планета і переїжджаєте ЗЕМЛЮ до МАРС.
Флетч

@ Fletch, Земля вже ближче до Сонця, ніж Марс ;-), але я розумію, що ти маєш на увазі. Однак у цьому випадку порядок планет насправді є функцією їх середньої відстані від Сонця, що не є простим порядковим, тому ІМХО краще зберігати як окреме поле для кожної планети. Тоді ви можете мати тривіальний порівняльник для порівняння планет на основі їх середньої відстані від Сонця та замовити їх за допомогою цього компаратора. Це ІМХО - чисте і безглузде рішення. Тоді як ваше рішення розривається, як, наприклад, новий колега вирішить, що планети, очевидно, повинні бути перелічені в алфавітному порядку ;-)
Péter Török

1
Ха-ха-е-е, так добре, все одно це змова, Марса немає. Спочатку я збирався використати Сатурн, але не міг пригадати, на якій планеті він знаходиться поруч, але план Марса, здається, повернувся назад :-). У будь-якому випадку ... в цьому випадку компаратор буде добре, але, очевидно, є необхідність вимагати більше коду. Я думаю, що якщо ви покладаєтесь на упорядкування вихідного коду, документування цього в коментарях класу було б добре. Ваш колега може навіть прочитати це.
Флетч

7

Інші відповіді хороші, але не коментуйте це:

"Це правило чи це не гарантується, що він не буде змінений у наступних випусках Jdk?"

Я не вірю, що гарантії на майбутні JDK існують, тому ви навіть не повинні їх турбувати. Не вдасться їх застосувати, майбутні керівники JDK можуть просто вирішити відмовитись від таких гарантій. Це як система Вестмінстерського парламенту: "Жоден парламент не може зв'язати майбутній парламент".

Однак, історія JDK виявляє чудову послідовність. Вони не вносять великих порушень, тому ви можете бути впевнені, що поточна визначена (а не лише спостережувана) поведінка буде збережена.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.