Rozumiem, że kompilator potrzebuje wyrażenia, aby było znane w czasie kompilacji, aby skompilować przełącznik, ale dlaczego Foo.BA_ nie jest stałą?
Chociaż są one stałe z punktu widzenia dowolnego kodu wykonywanego po zainicjowaniu pól, nie są one stałymi czasowymi kompilacji w sensie wymaganym przez JLS; zobacz §15.28 Wyrażenia stałe, aby poznać specyfikację wyrażenia stałego 1 . Odnosi się to do §4.12.4 Zmienne końcowe, które definiują „stałą zmienną” w następujący sposób:
Nazywamy zmienną typu pierwotnego lub typu String, która jest ostateczna i zainicjowana za pomocą wyrażenia stałego czasu kompilacji (§15.28) zmienną stałą. To, czy zmienna jest zmienną stałą, czy nie, może mieć wpływ na inicjalizację klasy (§12.4.1), zgodność binarną (§13.1, §13.4.9) i określone przypisanie (§16).
W naszym przykładzie zmienne Foo.BA * nie mają inicjatorów i dlatego nie kwalifikują się jako „zmienne stałe”. Poprawka jest prosta; zmień deklaracje zmiennych Foo.BA *, aby miały inicjatory, które są wyrażeniami stałymi czasu kompilacji.
W innych przykładach (gdzie inicjatory są już wyrażeniami stałymi czasu kompilacji), deklarowanie zmiennej jako final
potrzebnej.
Możesz zmienić kod tak, aby używał enum
zamiast int
stałych, ale wiąże się to z kilkoma innymi ograniczeniami:
1 - Ograniczenia stałych wyrażeń można podsumować w następujący sposób. Wyrażenia stałe a) mogą używać typów pierwotnych i String
tylko, b) zezwalać na operacje podstawowe, które są literałami (oprócz null
) i tylko zmiennymi stałymi, c) zezwalać na wyrażenia stałe, które mogą być ujęte w nawiasy jako podwyrażenia, d) zezwalać na operatory z wyjątkiem operatorów przypisania ++
, --
lub instanceof
, i e) zezwalaj na rzutowanie typów na typy pierwotne lub String
tylko.
Należy pamiętać, że to nie obejmuje żadnej formy lambda lub metody połączeń new
, .class
. .length
lub indeksowanie tablicy. Ponadto wszelkie użycie wartości tablicowych, enum
wartości, wartości pierwotnych typów opakowań, pudełek i rozpakowywania są wykluczone ze względu na a).