2016-06-26 25 views
0

ich durch diese Frage gehe Why would one declare an immutable class final in Java?Code-Beispiel dafür, wie ein Veränderliche Unterklasse-Objekt kann Problem verursachen, wenn unveränderliches Objekt erwartet wird

Ich verstand diese Answer aber ein Codebeispiel benötigen.

Ich schrieb es, aber hat einige Zweifel und würde schätzen, wenn jemand helfen kann.

public class Immutable { 
      private final int value; 

      public Immutable(int value) { 
       this.value = value; 
      } 

      public int getValue() { 
       return value; 
      } 

      public boolean equals(Object obj) { 
       return (obj instanceof Immutable 
          && getValue() == ((Immutable) obj).getValue()); 
       } 

      public int hashCode() { 
        int hash = 1; 
        hash = hash * 31 + value; 
        return hash; 
       } 
     } 

     public class Mutable extends Immutable { 
      private int realValue; 

      public Mutable(int value) { 
       super(value); 

       realValue = value; 
      } 

      public int getValue() { 
       return realValue; 
      } 
      public void setValue(int newValue) { 
       realValue = newValue; 
      } 
     } 

// test class main() 
    Mutable key = new Mutable(30); 
    Hashtable<Immutable, String> ht = new Hashtable<Immutable,String>(); 

    ht.put(new Immutable(10), "10"); 
    ht.put(new Immutable(20), "20"); 
    ht.put(key, "30"); 

    System.out.println("Hashcode : "+key.hashCode()+", \tKey : "+key.getValue()+" => Value : "+ht.get(key)); 

    key.setValue(40); 
    System.out.println("Hashcode : "+key.hashCode()+", \tKey : "+key.getValue()+" => Value : "+ht.get(key)); 

Output : 
Hashcode : 61, Key : 30 => Value : 30 
Hashcode : 61, Key : 40 => Value : 30 

Ich kann die Antwort mit diesem Code nicht beziehen.

Antwort

0

Ihr Code funktioniert, weil Ihre Methode hashCode das letzte Feld value aus der Klasse Immutable direkt verwendet, anstatt den Getter für das Feld zu verwenden. Dieses Feld wird nicht geändert, wenn die Methode setValue von Mutable verwendet wird, da diese Methode nur auf dem Feld realValue funktioniert.

Wenn Sie hashCode ändern

public int hashCode() { 
    int hash = 1; 
    hash = hash * 31 + getValue(); // use getter here 
    return hash; 
} 

Sie das unerwünschte Verhalten beobachten, wie in this answer beschrieben.

Es ist wichtig zu beachten, dass Ihr Code tatsächlich den gleichen Vertrag bricht. Als zwei Instanzen von Mutable zueinander gleich sein können, aber unterschiedlichen Hashcodes ...

+0

ich die Methode equals als Update: 'public boolean equals (Object obj) { \t return (obj instanceof Immutable && obj.hashCode() == this.hashCode() && getValue() == ((Immutable) obj) .getValue()); \t} ' –

+0

Dies wird den gleichen Vertrag erfüllen. Dies ist jedoch nicht wirklich beste Praxis. Betrachten Sie [diese Frage/Antwort] lesen (http://stackoverflow.com/questions/27581/what-issues-should-be-be-sidered-with-overriding-equals-and-hashcode-in-java) auf, wie man richtig einführt Gleich- und Hashcode-Methoden. – dpr