Bycie ostatecznym to nie to samo, co bycie niezmiennym.
final != immutable
Słowo final
kluczowe jest używane, aby upewnić się, że odniesienie nie zostanie zmienione (to znaczy, że odniesienie, które ma, nie może zostać zastąpione nowym)
Ale jeśli atrybut self jest modyfikowalny, możesz zrobić to, co właśnie opisałeś.
Na przykład
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Jeśli utworzymy instancję tej klasy, nie będziemy mogli przypisać innej wartości do atrybutu, someFinalObject
ponieważ tak jest ostateczny .
Więc to nie jest możliwe:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor;
Ale jeśli sam obiekt jest zmienny w następujący sposób:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Następnie wartość zawarta w tym zmiennym obiekcie może zostać zmieniona.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal );
Ma to taki sam efekt, jak Twój post:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Tutaj nie zmieniasz wartości INSTANCE, tylko modyfikujesz jej stan wewnętrzny (metoda, provider.add)
jeśli chcesz zapobiec zmianie definicji klasy w ten sposób:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
....
Ale to może nie mieć większego sensu :)
Nawiasem mówiąc, musisz również zsynchronizować dostęp do niego w zasadzie z tego samego powodu.