Быть окончательным - не то же самое, что быть неизменным.
final != immutable
final
Используется ключевое слово , чтобы убедиться , что ссылка не меняется (то есть ссылка она не может быть заменен на новый)
Но если атрибут является самодифицируемым, можно делать то, что вы только что описали.
Например
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();
}
....
Но это может не иметь большого смысла :)
Кстати, синхронизировать доступ к нему тоже нужно в основном по той же причине.