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 finalpotrzebnej.
Możesz zmienić kod tak, aby używał enumzamiast intstał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 Stringtylko, 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 Stringtylko.
Należy pamiętać, że to nie obejmuje żadnej formy lambda lub metody połączeń new, .class. .lengthlub indeksowanie tablicy. Ponadto wszelkie użycie wartości tablicowych, enumwartości, wartości pierwotnych typów opakowań, pudełek i rozpakowywania są wykluczone ze względu na a).