Бути остаточним - це не те саме, що бути незмінним.
final != immutable
final
Використовується ключове слово , щоб переконатися , що посилання не змінюється (тобто посилання вона не може бути замінений на новий)
Але, якщо атрибут self можна змінювати, це нормально робити те, що ви щойно описали.
Наприклад
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Якщо ми створимо екземпляр цього класу, ми не зможемо призначити інше значення атрибуту, someFinalObject
оскільки він є остаточним .
Отже, це неможливо:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor;
Але якщо об'єкт, який він сам, можна змінювати так:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Тоді значення, що міститься у цьому зміненому об'єкті, може бути змінено.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal );
Це має той самий ефект, що і ваша публікація:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Тут ви не змінюєте значення INSTANCE, ви змінюєте його внутрішній стан (за допомогою методу provider.add)
якщо ви не хочете, щоб визначення класу змінювалось так:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
....
Але, можливо, це не має великого сенсу :)
До речі, вам також доведеться синхронізувати доступ до нього в основному з тієї ж причини.