2012-07-22 22 views
27

Ok, quindi in Java 7 abbiamoObjects.hash() vs Objects.hashCode(), chiarimento necessario

o.hashCode(); 
    Objects.hashCode(o); 

    Objects.hash(o); 

I primi 2 sono più o meno lo stesso con il controllo di punto zero, ma ciò che è ultimo ?

Quando viene fornito un riferimento a un oggetto singolo, il valore restituito non è uguale al codice hash del riferimento a tale oggetto .

Perché è quello? Voglio dire, non abbiamo bisogno di 3 metodi che facciano la stessa cosa, lo capisco ... ma perché abbiamo bisogno di Objects.hash()? Quando sceglieresti di usarne uno contro l'altro?

risposta

47

Vedere la documentazione per hashCode e hash. hash prende Object... mentre hashCode prende Object. L'esempio dato è:

@Override public int hashCode() { 
    return Objects.hash(x, y, z); 
} 
  • Objects.hash(Object... values) dovrebbero essere utilizzati nei casi in cui si desidera un hash di una sequenza di oggetti, ad esempio, quando definisci il tuo metodo hashCode e vuoi un hash codificato semplicemente per più valori che costituiscono l'identità del tuo oggetto.
  • Objects.hashCode(Object o) deve essere utilizzato quando si desidera l'hash di un singolo oggetto, senza il lancio se l'oggetto è nullo.
  • Object::hashCode() deve essere utilizzato quando si desidera l'hash di un singolo oggetto e verrà generata un'eccezione se l'oggetto è nullo.

Nota che hash(o) e hashCode(o) non restituiranno necessariamente la stessa cosa! Se lo stai facendo per un singolo oggetto, probabilmente dovresti usare hashCode.

+0

In quale situazione "hash (o)" e "hashCode (o)" non restituiscono lo stesso valore? I documenti per 'hash()' state 'Attenzione: Quando viene fornito un riferimento a un singolo oggetto, il valore restituito non è uguale al codice hash di tale riferimento oggetto., Ma sto ancora scavando per capire perché. –

7

L'hashCode() predefinito di Object restituisce l'indirizzo di memoria per l'oggetto. Quindi, se avete la seguente classe:

class Car { 
    String make; 
    String model; 
    int year; 

    public Car(String make, String model, int year) { 
     this.make = make; 
     this.model = model; 
     this.year = year; 
    } 
} 

quindi creare due oggetti:

Car car1 = new Car("Toyota", "Corolla", 2010); 
Car car2 = new Car("Toyota", "Corolla", 2010); 

car1.hashCode() sarà diverso da car2.hashCode(), perché ogni oggetto avrà un indirizzo di memoria diverso .

E se si desidera che sia car1 che car2 restituiscano lo stesso codice hash? In questo caso, è necessario eseguire l'override del metodo predefinito Object hashCode() per la classe auto come segue:

@Override 
public int hashCode() { 
    Object[] x = {model, make, Integer.valueOf(year)}; 
    int hashArray = Arrays.hashCode(x); 
    return hashArray; 
} 

Questo renderà car1.hashCode() pari a car2.hashCode() perché lo String.hashCode() calcola l'hashCode in base al contenuto della stringa e Integer.hashCode() restituirà il valore intero stesso.

In Java 7, è possibile utilizzare solo Objects.hash (oggetti ... valori). Così la nostra nuova hashCode Car() avrà il seguente aspetto:

@Override 
public int hashCode() { 
    return Objects.hash(model, make, year); 
} 

Objects.hash (Object ... valori) chiamerà Arrays.hashCode per voi.

Infine, Objects.hashCode (Object o) eseguirà un controllo Null. Restituirà 0 se l'oggetto è nullo. Altrimenti, chiamerà il metodo hashCode() dell'oggetto.

+0

Il valore predefinito 'hashCode()' non ha restituito l'indirizzo di memoria per circa 20 anni. Non può davvero. GC sposta gli oggetti attorno. Il cosiddetto indirizzo di memoria è quello di un handle amovibile. – EJP

+0

Basato sul documento Java https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode "hashCode" viene in genere implementato convertendo l'indirizzo interno dell'oggetto in un numero intero, ma questa tecnica di implementazione non è richiesta dal linguaggio di programmazione Java ™. " – ezzadeen