Якщо ви робите foo
статичний, ви повинні ініціалізувати його в конструкторі класу (або в рядку, де ви його визначаєте), як у наступних прикладах.
Конструктор класів (не примірник):
private static final List foo;
static
{
foo = new ArrayList();
}
В лінію:
private static final List foo = new ArrayList();
Проблема тут полягає не в тому, як final
працює модифікатор, а в тому, як static
працює модифікатор.
final
Модифікатор нав'язує ініціалізацію довідки за часом виклику конструктор Завершує (тобто ви повинні ініціалізувати його в конструкторі).
Коли ви ініціалізуєте атрибут in-line, він ініціалізується перед запуском коду, який ви визначили для конструктора, і ви отримаєте такі результати:
- якщо
foo
є static
, foo = new ArrayList()
буде виконуватися до того , як static{}
конструктор ви визначили для свого класу виконуються
- якщо
foo
ні static
, foo = new ArrayList()
то буде виконано до запуску конструктора
Якщо ви не ініціюєте атрибут в рядку, final
модифікатор примушує його ініціалізувати, і ви повинні зробити це в конструкторі. Якщо у вас також є static
модифікатор, конструктор, у якому вам доведеться ініціалізувати атрибут, - це блок ініціалізації класу:static{}
.
Помилка, яку ви отримуєте у своєму коді, полягає в тому, що static{}
виконується під час завантаження класу, до моменту інстанцізації об'єкта цього класу. Таким чином, ви не будете ініціалізуватись foo
при створенні класу.
Подумайте про static{}
блок як конструктор для об'єкта типуClass
. Тут потрібно виконати ініціалізацію static final
атрибутів класу (якщо це не зроблено вбудовано).
Бічна примітка:
The final
Модифікатор запевняє константні-Несс тільки для примітивних типів і посилань.
Коли ви оголошуєте final
об'єкт, ви отримуєте цеfinal
посиланням на цей об’єкт, але сам об'єкт не є постійним.
Чого ви дійсно досягаєте при оголошенні final
атрибута, це те, що, коли ви оголосите об’єкт для вашої конкретної мети (наприклад, те, final List
що ви оголосили), для цього буде використаний той і лише цей об'єкт: ви не зможете змінитись List foo
на інший List
, але ви все одно можете змінити свої дані List
, додаючи / видаляючи елементи (використовувані List
вами будуть ті ж самі, лише зі зміненим вмістом).