Ser final não é o mesmo que ser imutável.
final != immutable
A final
palavra-chave é usada para garantir que a referência não seja alterada (ou seja, a referência que ela possui não pode ser substituída por uma nova)
Mas, se o atributo for self-modificável, não há problema em fazer o que você acabou de descrever.
Por exemplo
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Se instanciarmos essa classe, não poderemos atribuir outro valor ao atributo someFinalObject
porque ele é final .
Portanto, isso não é possível:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final
Mas se o próprio objeto é mutável assim:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Então, o valor contido por aquele objeto mutável pode ser alterado.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal ); // prints 3
Isso tem o mesmo efeito que sua postagem:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Aqui você não está alterando o valor de INSTANCE, você está modificando seu estado interno (por meio do método provider.add)
se você quiser evitar que a definição da classe seja alterada assim:
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 :)
....
Mas, pode não fazer muito sentido :)
A propósito, você também precisa sincronizar o acesso a ele basicamente pelo mesmo motivo.