Быть окончательным - это не то же самое, что быть неизменным.
final != immutable
Ключевое слово final
используется, чтобы убедиться, что ссылка не изменена (то есть ссылка, которую он не может заменить новой)
Но если атрибут self изменяемый, то можно делать то, что вы только что описали.
Например,
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Если мы создадим экземпляр этого класса, мы не сможем присвоить другое значение атрибуту someFinalObject
, потому что это final .
Так что это невозможно:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final
Но если объект сам изменчив, как это:
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 ); // prints 3
Это имеет тот же эффект, что и ваш пост:
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();
}
// Avoid modifications
//public static void addProvider(ConfigurationProvider provider) {
// INSTANCE.providers.add(provider);
//}
// No mutators allowed anymore :)
....
Но, это может не иметь особого смысла :)
Кстати, вам также нужно синхронизировать доступ к нему в основном по той же причине.