JLS 17.5.4 Запис захищених полів :
Зазвичай остаточні статичні поля не можуть бути змінені. Однак System.in
, System.out
і System.err
є остаточними статичними полями, яким із застарілих причин потрібно дозволити змінювати методи System.setIn
, System.setOut
та System.setErr
. Ми називаємо ці поля захищеними від запису, щоб відрізнити їх від звичайних кінцевих полів.
Компілятор повинен поводитися з цими полями інакше, ніж з іншими кінцевими полями. Наприклад, зчитування звичайного кінцевого поля є "імунітетом" до синхронізації: бар'єр, який бере участь у блокуванні або мінливому зчитуванні, не повинен впливати на те, яке значення зчитується з кінцевого поля. Оскільки значення захищених від запису полів може змінюватися, події синхронізації повинні впливати на них. Отже, семантика диктує, що ці поля повинні розглядатися як звичайні поля, які не можна змінити за допомогою коду користувача, якщо тільки цей код користувача не знаходиться в System
класі.
До речі, насправді ви можете мутувати final
поля за допомогою відображення, викликаючи setAccessible(true)
їх (або використовуючи Unsafe
методи). Такі методи використовуються під час десериалізації, Hibernate та іншими фреймворками тощо, але вони мають одне обмеження: код, який бачив значення остаточного поля до модифікації, не гарантовано бачить нове значення після модифікації. Особливість розглянутих полів полягає в тому, що вони позбавлені цього обмеження, оскільки компілятор обробляє їх особливим чином.