Я розумію, що компілятору потрібен вираз, який потрібно знати під час компіляції, щоб скласти комутатор, але чому Foo.BA_ не є постійним?
Хоча вони постійні з точки зору будь-якого коду, який виконується після ініціалізації полів, вони не є константою часу компіляції у тому сенсі, який вимагає JLS; див. § 15.28 Постійні вирази для уточнення константного виразу 1 . Це стосується §4.12.4 Кінцеві змінні, яка визначає "постійну змінну" наступним чином:
Ми називаємо змінну, примітивного типу або типу String, яка є остаточною і ініціалізується постійним виразом часу компіляції (§15.28) постійною змінною. Будь змінна є постійною змінною чи ні, може мати наслідки щодо ініціалізації класів (§12.4.1), бінарної сумісності (§13.1, §13.4.9) та визначеного призначення (§16).
У вашому прикладі змінні Foo.BA * не мають ініціалізаторів, а значить, не кваліфікуються як "постійні змінні". Виправлення просте; змінити декларації змінної Foo.BA * на ініціалізатори, які є постійними виразами часу компіляції.
В інших прикладах (де ініціалізатори вже є постійними виразами часу компіляції), оголошуючи змінну такою, що final
може бути необхідною.
Ви можете змінити свій код, щоб enum
скоріше використовувати int
константи, але це приносить ще кілька різних обмежень:
1 - Обмеження постійного вираження можна узагальнити наступним чином. Постійні вирази a) можуть використовувати примітивні типи і String
лише, b) дозволяють праймери, які є буквальними (крім null
) та лише постійними змінними, c) дозволяють постійні вирази, можливо, укрупнені як субекспресії; d) дозволяють операторам за винятком операторів призначення ++
, --
або instanceof
, і д) дозволяють виконувати типові типи String
лише примітивних типів .
Зверніть увагу , що це не відноситься до якоїсь - якій формі методу або лямбда - викликів new
, .class
. .length
або підписка на масив. Крім того, будь-яке використання значень масивів, enum
значень, значень примітивних типів обгортки, боксу та розпакування виключається через a).