Être définitif n'est pas la même chose qu'être immuable.
final != immutable
En final
est utilisé pour s'assurer que la référence n'est pas modifiée (c'est-à-dire que la référence qu'il possède ne peut pas être remplacée par une nouvelle référence).
Mais, si l'attribut est modifiable, il est possible de faire ce que vous venez de décrire.
Par exemple
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Si nous instancions cette classe, nous ne pourrons pas attribuer une autre valeur à l'attribut someFinalObject
parce que c'est final .
Ce n'est donc pas possible :
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final
Mais si l'objet lui-même est mutable comme ceci :
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Ensuite, la valeur contenue dans cet objet mutable peut être modifiée.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal ); // prints 3
Cela a le même effet que votre poste :
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Ici, vous ne changez pas la valeur de l'INSTANCE, vous modifiez son état interne (via la méthode providers.add).
si vous voulez empêcher cela, la définition de la classe doit être modifiée comme ceci :
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 :)
....
Mais, cela pourrait ne pas avoir beaucoup de sens :)
Au fait, vous devez aussi synchroniser son accès essentiellement pour la même raison.
0 votes
Cette idée fausse revient assez souvent, pas nécessairement sous forme de question. Souvent sous forme de réponse ou de commentaire.
5 votes
Une explication simple de JLS : "Si une variable finale contient une référence à un objet, alors l'état de cet objet peut être modifié par des opérations sur l'objet, mais la variable fera toujours référence au même objet." Documentation JLS