2009-06-30 14 views
10

Il comportamento predefinito di Object.hashCode() è di restituire essenzialmente "l'indirizzo" dell'oggetto in modo che a.hashCode() == b.hashCode() se e solo se a == b . Come posso ottenere questo comportamento in una classe definita dall'utente se una superclasse già definisce hashCode()? Ad esempio:Codice hash Java basato sull'identità

class A { 
    public int hashCode() { 
    return 0; 
    } 
} 

class B extends A { 
    public int hashCode() { 
    // Now I want to return a unique hashcode for each object. 
    // In pythonic terms, it'd look something like: 
    return Object.hashCode(this); 
    } 
} 

Idee?

+1

No, non lo è. È per ottenere un codice in modo che a.hashCode()! = B.hashCode() implichi necessariamente che a! = B. –

+3

... ma a.hashCode() == b.hashCode() non implica un == b che avrei dovuto aggiungere. –

+1

se "a.equals (b)", non necessariamente "a == b", allora i codici hash devono essere uguali: "a.hashCode() == b.hashCode()" –

risposta

25

System.identityHashCode(Object) fornisce questo comportamento.

Si potrebbe scrivere questo:

class B extends A { 
    public int hashCode() { 
    return System.identityHashCode(this); 
    } 
} 

Si prega di controllare il pari-metodo, che restituisce solo vero, se i due oggetti sono gli stessi. In caso contrario, si interromperà il comportamento descritto per equals e hashCode. (Per essere corretto, il pari-metodo deve restituire false, se si ottiene diversi codici hash per due oggetti.) Per fornire un'implementazione di equals() che rispettano la data hashCode() - Metodo:

public boolean equals(Object other){ 
    return this == other; 
} 
9

Utilizzare System.identityHashCode(). Questo è quello che usa IdentityHashMap.

Si dovrebbe essere estremamente diffidare di rilevante un hashCode() esistente con questo, però, perché si potrebbe rompere il contratto hashCode, è che due oggetti che:

se a.equals (b) poi a.hashCode() deve essere uguale a b.hashCode()

Si può rompere questo sovrascrivendo il comportamento esistente o potrebbe essere necessario sovrascrivere anche equals().

1

Come Meementh ha detto tutto, vorrei solo sottolineare che hashCode() restituisce 0 (o qualsiasi valore costante) è valido (mentre lame). hashCode() può (e dovrebbe) restituire valori diversi per aeb solo se! a.equals (b).
Così, per esempio, si hanno

class A { 
    public int hashCode() { 
    return 0; 
    } 
    public boolean equals(Object o) { 
    return o instanceof A; // all objects are equal 
    } 
} 

class B extends A { 
    public int hashCode() { 
    return System.identityHashCode(this); 
    } 
    public boolean equals(Object o) { 
    return this.hashCode().equals(o.hashCode()); 
    } 
} 

Ora si crea due oggetti:

A a = new A(); 
A b = new B(); 

E improvvisamente a.equals (b), ma b.equals (a)!. Naturalmente nella vita reale gli uguali() in A saranno più sofisticati, ma il problema persiste ancora. Per sbarazzarsi di questo problema che si desidera chiamare sempre

if (super.equals(o)) return true; 

all'inizio del nuovo equals().

E poiché override hashCode() è strettamente legato a override di equals(), si vuole essere sicuri che ovunque super.equals() restituisca true per ogni dato oggetto, il nuovo hashCode() restituirà super.hashCode() .

Problemi correlati