2013-02-08 14 views

risposta

14

Sì, ha ragione: tuttavia, se è necessario inserire gli oggetti in una raccolta basata su hash un giorno, sarà necessario aggiungere hashcode ovunque, il che può essere fastidioso + in quel giorno potresti implementare il codice hash in modo errato (cioè non coerente con gli uguali) perché si perde qualche sottigliezza nel metodo di uguaglianza ...

Considerando che la maggior parte degli IDE fornisce una funzione di generazione automatica di uguali/hash, vedo poche ragioni per non crearli entrambi.

Un altro modo per esaminarlo è: quando si esegue l'override di un metodo da una classe padre, è necessario seguire il contratto definito da tale classe genitore. Nel caso di oggetti, il javadoc of equals è abbastanza chiaro:

noti che è generalmente necessario ridefinire il metodo hashCode ogniqualvolta viene sovrascritto questo metodo, in modo da mantenere il contratto generale per il metodo hashCode, che afferma che gli oggetti uguali devono avere uguali codici hash.

Quindi, se non avete un motivo di progettazione vera e propria, non per ignorare codice hash, la decisione di default dovrebbe essere quello di seguire il contratto classe padre e sovrascrivere né o entrambi.

+2

+1 Ma d'altra parte, se 'equals' è ciò che il codice dipende da ora, c'è una possibilità molto alta di' hashCode' di rimanere indietro rispetto alle modifiche a 'equals', che ancora una volta finisce con l'essere incoerente con esso. Il miglior compromesso, ai miei occhi, sarebbe un semplice 'return 1; '--- almeno è tecnicamente corretto. –

+7

Il mio problema con 'return 1;' è che sembra probabile che porti a problemi di prestazioni silenziosi e difficili da debug se usi 'HashSet' più tardi. Invece, implementerei 'hashCode()' come 'throw new UnsupportedOperationException()', che richiede uno sforzo minimo, ma rende ovvio quando si torna indietro e si usa 'HashSet' più tardi che non si è preoccupato di implementare' hashCode () 'la prima volta. –

+1

@LouisWasserman Lanciare un'eccezione se * davvero * non si vuole implementare hashcode è davvero una buona idea. – assylias

0

Generale:

sostituita solo quei metodi che si desidera utilizzare nel proprio modo e anche quei metodi che sono colpiti da questo imperativo.

specifico per la tua Ques:

Da docs java,

Si noti che è generalmente necessario eseguire l'override del metodo hashCode ogni volta equals() viene ignorato, in modo da mantenere il generale contratto per il metodo hashCode, che stabilisce che gli oggetti uguali devono avere uguali codici hash.

Equals

+0

Questo è generalmente vero, ma l'uguaglianza e l'hashcode sono realmente intesi per essere coerenti: ignorare nessuno o entrambi è la scelta predefinita, il che li rende incoerenti (ignorando solo uno di essi) è una decisione importante sul design. – assylias

+0

Penso che ora abbia un senso nel mio ans. – Arpit

4

E 'un codice di odore. Findbugs ad esempio ti avviserà se hai override o hashCode o equals senza sovrascrivere l'altro. È necessario eseguire l'override di entrambi in modo che siano coerenti tra loro (ovvero a.equals (b) => a.hashCode() == b.hashCode()).

Un piccolo sforzo ora potrebbe far risparmiare un sacco di mal di testa in seguito.

+0

o ..avere hashCode su una classe non progettata per essere una chiave (essendo mutabile per esempio) può causare un sacco di problemi in seguito. L'hashCode non sottoposto a override verrà catturato immediatamente, dopo aver rotto hashCode è molto più difficile da tracciare. – bestsss

+0

se non si presume che sia una chiave in una struttura hash, si può generare un'eccezione all'interno di hashcode ... c'è un precedente per questo nei buffer del protocollo di Google quando il messaggio del protocollo contiene un MessageSet – sjr

+0

Mentre una buona soluzione se ha il potente per rompere il codice esistente (nel complesso nessuno si aspetta che 'hashCode()' lanci un'eccezione). Conosco codice che usa hashCode per verificare null (vale a dire in attesa di NPE) [false getClass() sarebbe stato meglio] - quindi, di nuovo potrebbe essere ok - ma proporlo come predefinito è un po 'rischioso. – bestsss

5

Se si esegue l'override di equals(), ignorare anche hashCode(). Anche se non usi ora hashCode(), tu o qualcun altro potrebbe usarlo.

Per ulteriori informazioni su questo argomento, controllare l'eccellente SO answer

0

In realtà per scontato che si creano due oggetti differenti senza sostituire eguali e metodi hashCode.E poi se chiamate il metodo equals, java chiama il metodo hashCode in modo implicito, quindi controlla l'uguaglianza di hashcode.

L'override del metodo hashCode è sufficiente per controllare l'uguaglianza di due oggetti. E sarà utile per il futuro. Puoi usare questo corso sulle raccolte.

Altrimenti se si implementa un metodo uguale, risolverà solo l'uguaglianza di due oggetti non più.

+0

Java non chiama implicitamente 'hashCode' per l'implementazione predefinita di' equals'. Verifica che due oggetti puntino allo stesso riferimento usando '=='. Si può avere 'hashCode' restituire un valore casuale su ogni chiamata e l'implementazione predefinita di' equals' funzionerà ancora se si punta allo stesso oggetto. –

+0

L'istruzione relativa al controllo dell'eguaglianza mediante hashCode() è in realtà errata. Lo stesso codice hash non garantisce l'uguaglianza. – ATrubka

+0

Sì Indica che hai ragione controlla i riferimenti. ATrubka, nella mia risposta ho specificato in particolare che l'implementazione predefinita della classe Object verrà utilizzata per il mio esempio. Le altre possibilità non specificate nella mia risposta. – emin

1

È necessario eseguire l'override di hashCode in ogni classe che esegue l'override su uguali. In caso contrario, si verificherà una violazione del contratto generale per Object.hashCode, che impedirà il corretto funzionamento della classe in combinazione con tutte le raccolte basate su hash, inclusi HashMap, HashSet e Hashtable.

Java efficace Articolo 9: Sostituisce sempre hashCode quando si esegue l'override su uguali.

Se la classe è una classe pubblica, non è possibile controllare l'utilizzo delle classi nello sviluppo futuro. Senza guardare nel codice sorgente (o attraverso la riflessione) non c'è modo di sapere se questa classe ha sovrascritto il metodo hasCode o meno e l'utente sarà sorpreso dal risultato se lo usa in qualsiasi raccolta basata su hash.

+0

È vero! Penso che probabilmente il mio collaboratore non abbia pensato di rilasciare il suo codice per altre persone e che probabilmente sarà la persona principale che lavora sul framework. – user1739658

Problemi correlati