Question

Je suis tombé sur le code suivant dans une base de code, je travaille sur:

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }

    public static void addProvider(ConfigurationProvider provider) {
        INSTANCE.providers.add(provider);
    }

    ...

INSTANCE est déclarée comme final. Pourquoi les objets peuvent être ajoutés à INSTANCE? Il ne faut pas que invalidera l'utilisation finale. (Il ne fonctionne pas).

Je suppose que la réponse doit faire quelque chose avec des pointeurs et de la mémoire, mais je voudrais savoir à coup sûr.

Était-ce utile?

La solution

final fait simplement l'objet référence inchangeable. L'objet il pointe est pas immuable en faisant cela. INSTANCE ne peut jamais se référer à un autre objet, mais l'objet auquel il se réfère à peut changer d'état.

Autres conseils

Être final n'est pas la même chose qu'être immuable.

final != immutable

Le mot-clé final est utilisé pour assurer que la référence ne change pas (c'est la référence qu'il est ne peut pas être substitué par un nouveau)

Mais, si l'attribut est auto est modifiable, il est autorisé à faire ce que vous venez de décrire.

Par exemple

class SomeHighLevelClass {
    public final MutableObject someFinalObject = new MutableObject();
}

Si nous instancier cette classe, nous ne serons pas en mesure d'attribuer une autre valeur à l'someFinalObject d'attribut car il est finale .

Donc, ce n'est 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 par cet objet mutable peut être modifié.

SomeHighLevelClass someObject = new SomeHighLevelClass();

someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();

System.out.println( someObject.someFinal ); // prints 3

a le même effet que votre message:

public static void addProvider(ConfigurationProvider provider) {
    INSTANCE.providers.add(provider);
}

Ici, vous ne changez pas la valeur de l'instance, vous êtes en train de modifier son état interne (via, méthode providers.add)

si vous voulez éviter que la définition de la classe devrait être modifiée comme suit:

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, il pourrait ne pas avoir beaucoup de sens :)

Par ailleurs, vous pouvez également synchroniser l'accès à elle essentiellement pour la même raison.

La clé du malentendu est dans le titre de votre question. Ce n'est pas objet qui est définitive, il est variable . La valeur de la variable ne peut pas changer, mais les données qu'il peut.

Rappelez-vous toujours que lorsque vous déclarez une variable de type de référence, la valeur de cette variable est une référence, pas un objet.

finale signifie simplement que la référence ne peut pas être changé. Vous ne pouvez pas réaffecter à une autre référence INSTANCE si elle est déclarée comme définitive. L'état interne de l'objet est toujours mutable.

final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;

jetterait une erreur de compilation

  

Une fois une variable final a été attribué, il contient toujours la même valeur. Si une variable final contient une référence à un objet, l'état de l'objet peut être modifié par des opérations sur l'objet, mais la variable sera toujours référence au même objet. Cela vaut également pour les tableaux, car les tableaux sont des objets; si une variable final contient une référence à un tableau, les composants du réseau peuvent être modifiés par des opérations sur le tableau, mais la variable sera toujours référence au même tableau.

Source

Voici un guide sur faire un objet immuable .

final et immuable ne sont pas la même chose. signifie la référence finale ne peut être réaffecté vous pouvez pas dire

INSTANCE = ...

inaltérables signifie que l'objet lui-même ne peut pas être modifié. Un exemple de ceci est la classe java.lang.String. Vous ne pouvez pas modifier la valeur d'une chaîne.

Java ne pas le concept de l'immuabilité construit dans la langue. Il n'y a aucun moyen de marquer des méthodes comme mutator. Par conséquent, la langue n'a aucun moyen d'appliquer immuabilité objet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top