2009-09-09 5 views
29

Esiste un metodo nel JDK che confronta due oggetti per l'uguaglianza, che tiene conto di null? Qualcosa di simile a questo:Confronto di due oggetti con un controllo per null

public static boolean equals(Object o1, Object o2) 
{ 
    if (o1 == null) 
    { 
     return o2 == null; // Two nulls are considered equal 
    } 
    else if (o2 == null) 
    { 
     return false; 
    } 

    return o1.equals(o2); 
} 

Sembra stupido a scrivere questo metodo me stesso in quanto Vorrei pensare che deve esistere già da qualche parte.

risposta

51

Java 7.0 ha aggiunto una nuova classe a portata di mano: Objects.

Ha un metodo proprio per questo: Objects.equals(Object a, Object b)

+0

Bene, tenete presente che Java 7 non è ancora universalmente disponibile. Generalmente cerco di non utilizzare un'API finché la sua implementazione non ha raggiunto almeno il 95% –

+1

@EdwardFalk Sì, e si tenga presente che Java 7 (o qualsiasi altra versione) non raggiungerà mai il 100% di disponibilità in assoluto. Oggi è il 12 luglio 2015, Java 7 ha esattamente 4 anni, Java 6 ha ** 9 anni **. Anche Java 7 ha raggiunto ** la fine della vita **, il che significa che non ci saranno più aggiornamenti pubblici anche per Java 7. Perché dovresti incoraggiare l'utilizzo dell'unica API Java 6.0? Sì, ci sono computer che hanno solo Java 6.0, ma personalmente non voglio sviluppare software per sistemi di età decennale, a scapito di rinunciare alle funzionalità aggiunte in Java 7 e 8. – icza

+0

Sì, questo è il mio stile di lavoro . Ho iniziato a utilizzare solo le funzionalità di Java 6 negli ultimi anni e non utilizzo ancora le funzionalità di Java 7 o 8. Sono stato così per tutta la vita; Non ho iniziato ad usare Ansi C fino a quando K & R C non era più disponibile da nessuna parte. Userò nuove funzionalità quando ne avrò bisogno, ma quando possibile, preferisco che il mio codice venga compilato ed eseguito ovunque. –

4

Se siete preoccupati per NullPointerExceptions si può solo testare l'uguaglianza come:

if (obj1 != null && obj1.equals(obj2)) { ... } 

Il contratto generale di equals() è che un oggetto non nullo non dovrebbe mai essere uguale ad un riferimento null, e che il metodo equals() dovrebbe restituire false se si sta confrontando un oggetto con un riferimento null (e non si lancia un NPE).

+2

uso questa logica in altri scenari, ma qui specificamente vogliono due nulli per essere considerati uguali (e quindi eseguire la clausola true). Per fare ciò in linea sarebbe piuttosto prolisso: if ((obj1 == null && obj2 == null) || (obj1! = Null && obj1.equals (obj2))) {...} – dcstraw

+1

Questo è uno di quelli costrutti (come controllare una stringa per null e vuoto o chiudere un flusso senza preoccuparsi di una IOException) che è duro per gli occhi e per il quale Commons-lang ha una soluzione per. – SingleShot

+0

Sono d'accordo con SingleShot e uso spesso commons-lang per cose come questa. –

17

Apache Commons Lang ha un tale metodo: ObjectUtils.equals(object1, object2). Non si vogliono i generici con questo metodo, ma si verificheranno errori di compilazione falsi, almeno in generale. Equals sa molto bene (o dovrebbe - fa parte del contratto) controllare la classe dell'oggetto e restituire false, quindi non ha bisogno di alcun tipo di sicurezza aggiuntivo.

+0

Sì, suppongo che i generici in realtà non ti comprino nulla in questo caso. Potresti ancora passare in tipi completamente diversi e l'inferenza del tipo selezionerà semplicemente Object come parametro type. Non sono sicuro di cosa siano gli "errori di compilazione falsi" a cui ti stai riferendo. – dcstraw

+0

Ho sicuramente visto i tentativi di fare generici come quello hanno problemi (con parametri generici e simili). Non potrei riprodurlo rapidamente in questo scenario, quindi potresti avere ragione, ma se così fosse, allora i generici non hanno senso, poiché accettano qualsiasi cosa, quindi perché non dichiarare semplicemente Oggetto? – Yishai

+1

concordato. L'utilizzo di Object è migliore in questo caso. – dcstraw

2

Ogni volta che mi imbatto in un bisogno e penso "questo è così comune che Java deve averlo" ma non lo trova, controllo il progetto Jakarta Commons. Lo ha quasi sempre. Una rapida ricerca dell'API commons-lang (che ha il più semplice dei comuni programmi di utilità) mostra un metodo equals() che fornisce ciò che desideri.

14

FWIW, questa era la mia realizzazione:

private static boolean equals(Object a, Object b) { 
    return a == b || (a != null && a.equals(b)); 
} 

Nella mia domanda, so che A e B saranno sempre dello stesso tipo, ma io sospetto che funzioni bene anche se non lo sono, a condizione che a.equals() sia ragionevolmente implementato.

+2

Il nuovo modo è 'Objects.equals (Object a, Object b)' – tmin

+1

Nuovo in 1.7. Bello. –

+0

'return (a == null)? (a == b): a.equals (b); 'sembra molto più leggibile di quello che hai lì (anche se chiama uguale per lo stesso oggetto). – Dukeling

5
public static boolean equals(Object object1, Object object2) { 
    if (object1 == null || object2 == null) { 
     return object1 == object2; 
    } 
    return object1.equals(object2); 
}