2010-09-03 14 views
106

A partire da Java 1.5, è possibile interscambiare praticamente Integer con int in molte situazioni.Java: intero uguale a ==

Tuttavia, ho trovato un potenziale difetto nel mio codice che mi ha sorpreso un po '.

Il codice seguente:

Integer cdiCt = ...; 
Integer cdsCt = ...; 
... 
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt) 
    mismatch = true; 

sembrava essere l'impostazione errata disallineamento quando i valori sono uguali, anche se non è possibile determinare in quali circostanze. Ho impostato un punto di interruzione in Eclipse e ho visto che i valori di Integer erano entrambi 137, e ho controllato l'espressione booleana e ho detto che era falso, ma quando l'ho scavalcato, è stata impostata la corrispondenza errata su true.

Modifica del condizionale:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt)) 

risolto il problema.

Qualcuno può far luce sul motivo per cui è successo? Finora, ho visto solo il comportamento sul mio localhost sul mio PC. In questo caso particolare, il codice ha superato con successo circa 20 confronti, ma non è riuscito su 2. Il problema è stato costantemente riproducibile.

Se si tratta di un problema prevalente, dovrebbe causare errori negli altri ambienti (dev e test), ma finora nessuno ha segnalato il problema dopo centinaia di test nell'esecuzione di questo snippet di codice.

Non è ancora legittimo utilizzare == per confrontare due valori Integer?

In aggiunta a tutte le risposte corrette di seguito, il seguente link StackOverflow ha un bel po 'di informazioni aggiuntive. In realtà avrebbe risposto alla mia domanda iniziale, ma perché non ho menzionato autoboxing nella mia interrogazione, non ha mostrato nelle proposte selezionate:

Why can't the compiler/JVM just make autoboxing “just work”?

risposta

177

La JVM memorizza nella cache valori interi. == funziona solo per i numeri tra -128 e 127 http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

+1

Grazie, questo sicuramente spiega perché 137 fallisce! E risponde anche alla mia domanda sul perché non si tratta di un problema prevalente, nel 95% dei casi che ho intenzione di incontrare, il valore sarebbe inferiore a 127. Buono per catturarlo ora però per il 5% dove non lo è. –

+0

Interessante nota a margine: fino a un paio di settimane fa, cdiCt e cdsCt erano entrambi intatti quindi andava bene, ma dovevo renderli interi per verificare la situazione nulla che viene gestita in modo diverso ... –

+2

@Jeremy Sì, è un problema piuttosto oscuro, ma come regola generale si usa .equals() per Objects e == per primitive. Non puoi fare affidamento su Autounboxing per il test di uguaglianza. – Adam

5

Il problema è che i due oggetti sono Integer solo quello, oggetti. Non corrispondono perché stai confrontando i tuoi riferimenti a due oggetti, non i valori all'interno. Ovviamente .equals è sovrascritto per fornire un confronto di valori al contrario di un confronto di riferimenti a oggetti.

+0

buona risposta, ma non spiega perché è solo in mancanza di 137. –

+0

Doh, ho perso quella parte. – MattC

4

Integer fa riferimento al riferimento, ovvero quando si confrontano i riferimenti che si stanno confrontando se puntano allo stesso oggetto, non al valore. Quindi, il problema che stai vedendo. Il motivo per cui funziona così bene con i tipi semplici int è che cancella il valore contenuto dallo Integer.

Posso aggiungere che se stai facendo quello che stai facendo, perché l'istruzione if inizia?

mismatch = (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt)); 
+2

Buon punto, ma non sto facendo quello che sto facendo. È stato semplificato –

+0

Ecco come dovrebbe essere scritto il codice e questa dovrebbe essere la risposta accettata. ** Sempre ** confronta gli oggetti con .equals(). Perché utilizzare gli Integi memorizzati nella cache e lasciare il tuo codice al caso? – NobleUplift

61

Non è possibile confrontare due Integer con un semplice == sono gli oggetti in modo maggior parte dei riferimenti di tempo non sarà lo stesso.

C'è un trucco, con Integer tra -128 e 127, i riferimenti saranno gli stessi di Autoboxing utilizza Integer.valueOf() che memorizza nella cache piccoli numeri interi.

Se il valore p essere inscatolato è vero, falso, un byte, un char nell'intervallo \ u0000 a \ u007F, o un int o numero breve tra -128 e 127, poi lasciare r1 e r2 sia la risultati di due conversioni di boxing di p. È sempre il caso che r1 == r2.


Risorse:

Sullo stesso argomento:

+0

Grazie, ho segnato la prima risposta come quella giusta però. –

+0

oh, immagino di poterli contrassegnare entrambi correttamente. Segno di spunta anche per te. –

+0

@Jeremy, in realtà è possibile contrassegnarne solo uno come giusto. Facendo clic sul segno di spunta una seconda volta cambia solo la risposta accettata. Non essere meschino; La risposta di Colin è eccellente. :) – Adam

1

"==" confronta sempre la posizione di memoria oi riferimenti a oggetti dei valori. il metodo equals confronta sempre i valori. Ma eguaglia anche indirettamente l'operatore "==" per confrontare i valori.

L'intero utilizza la cache dei numeri interi per memorizzare i valori da -128 a +127. Se l'operatore == viene utilizzato per verificare eventuali valori compresi tra -128 e 127, restituisce true. per un valore diverso da questi valori restituisce false.

deferire la link per alcune ulteriori informazioni