JLS 17.5.4 Pola chronione przed zapisem :
Zwykle końcowe pola statyczne nie mogą być modyfikowane. Jednak System.in
, System.out
i System.err
są ostatecznymi polami statycznymi, które ze starszych powodów muszą mieć możliwość zmiany za pomocą metod System.setIn
, System.setOut
i System.setErr
. Odnosimy się do tych pól jako chronionych przed zapisem, aby odróżnić je od zwykłych pól końcowych.
Kompilator musi traktować te pola inaczej niż inne końcowe pola. Na przykład odczyt zwykłego pola końcowego jest „odporny” na synchronizację: bariera związana z blokadą lub odczytem zmiennym nie musi wpływać na wartość odczytywaną z pola końcowego. Ponieważ wartość pól chronionych przed zapisem może się zmieniać, zdarzenia synchronizacji powinny mieć na nie wpływ. Dlatego semantyka nakazuje, aby te pola były traktowane jak zwykłe pola, których nie można zmienić za pomocą kodu użytkownika, chyba że ten kod użytkownika znajduje się w System
klasie.
Nawiasem mówiąc, w rzeczywistości możesz mutować final
pola przez odbicie, wywołując setAccessible(true)
je (lub używając Unsafe
metod). Takie techniki są używane podczas deserializacji, przez Hibernate i inne frameworki itp., Ale mają jedno ograniczenie: kod, który widział wartość końcowego pola przed modyfikacją, nie gwarantuje, że zobaczy nową wartość po modyfikacji. Cechą szczególną tych pól jest to, że są one wolne od tego ograniczenia, ponieważ są one traktowane w specjalny sposób przez kompilator.