Essere definitivi non è la stessa cosa che essere immutabile.
final != immutable
La final
parola chiave viene utilizzata per assicurarsi che il riferimento non venga modificato (ovvero, il riferimento che ha non può essere sostituito con uno nuovo)
Ma, se l'attributo è self è modificabile, va bene fare ciò che hai appena descritto.
Per esempio
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Se istanziamo questa classe, non saremo in grado di assegnare un altro valore all'attributo someFinalObject
perché è definitivo .
Quindi questo non è possibile:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor;
Ma se l'oggetto stesso è mutabile in questo modo:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Quindi, il valore contenuto da quell'oggetto mutabile può essere modificato.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal );
Questo ha lo stesso effetto del tuo post:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Qui non stai cambiando il valore di INSTANCE, stai modificando il suo stato interno (tramite il metodo provider.add)
se vuoi evitare che la definizione della classe debba essere modificata in questo modo:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
....
Ma potrebbe non avere molto senso :)
A proposito, devi anche sincronizzare l'accesso ad esso fondamentalmente per lo stesso motivo.