2010-09-11 12 views
10

MODIFICA: OK, OK, ho letto male. Non sto confrontando un int con un intero. Debitamente annotato.Che cosa fa esattamente il confronto degli interi con ==?

Il mio libro SCJP dice:

Quando == viene utilizzato per confrontare un primitivo ad un involucro, l'involucro sarà scartato e il confronto sarà primitiva alla primitiva.

Quindi si potrebbe pensare che questo codice dovrebbe stampare true:

Integer i1 = 1; //if this were int it'd be correct and behave as the book says. 
    Integer i2 = new Integer(1); 
    System.out.println(i1 == i2); 

ma esso stampa false.

Inoltre, secondo il mio libro, questo dovrebbe stampare true:

Integer i1 = 1000; //it does print `true` with i1 = 1000, but not i1 = 1, and one of the answers explained why. 
Integer i2 = 1000; 
System.out.println(i1 != i2); 

Nope. È false.

Cosa dà?

+0

Ecco, io non sono sicuro se questa parte del libro è scritto male o sono un idiota, ma non riesco a capire cosa dice la ragione. Il mio miglior tentativo di comprensione è che == sia trattato diversamente da! =. Forse == riflette l'uguaglianza di valore (uguaglianza profonda) ma! = No. In ogni caso, quello che dice il libro non accade comunque all'IRL. –

+0

No, il problema in questo caso si trova nei due tipi che stai confrontando. == e! = si comportano allo stesso modo. – EboMike

+0

Solo questo esempio è sufficiente per farmi pensare che Java sia una specie di scherzo malato invece di un vero linguaggio di programmazione. – dsimcha

risposta

8
Integer i1 = 1; 
Integer i2 = new Integer(1); 
System.out.println(i1 == i2); 

Quando si assegna 1-i1 tale valore è inscatolato, creazione di un oggetto Integer. Il confronto confronta quindi i due riferimenti a oggetti. I riferimenti non sono uguali, quindi il confronto fallisce.

Integer i1 = 100; 
Integer i2 = 100; 
System.out.println(i1 != i2); 

Perché questi sono inizializzati con costanti di compilazione il compilatore può e loro interno e rende entrambi verso il medesimo Integer oggetto.

(Si noti che ho cambiato i valori da 1000 a 100. Come @NullUserException sottolinea, solo piccoli numeri interi sono internati.)


Ecco un test davvero interessante. Vedi se riesci a capirlo. Perché il primo programma stampa true, ma il secondo è false? Usando la vostra conoscenza di analisi boxe e compilatore volta che si dovrebbe essere in grado di capire questo:

// Prints "true". 
int i1 = 1; 
Integer i2 = new Integer(i1); 
System.out.println(i1 == i2); 

// Prints "false". 
int i1 = 0; 
Integer i2 = new Integer(i1); 
i1 += 1; 
System.out.println(i1 == i2); 

Se si capisce quanto sopra, cercare di prevedere ciò che questo programma stampa:

int i1 = 0; 
i1 += 1; 
Integer i2 = new Integer(i1); 
System.out.println(i1 == i2); 

(Dopo averlo indovinato, run it and see!)

+0

* Questo è importante in quanto sono internati solo i piccoli numeri interi. * - Tenere presente che solo "Integer" mantiene solo una cache interna che usa (per detti piccoli valori) quando viene eseguita una chiamata a "valueOf"; il compilatore genera ancora due righe di 'invokestatic java/lang/Integer/valueOf (I) Ljava/lang/Integer;' –

6

Non stai confrontando un primitivo con un wrapper. Stai confrontando due wrapper (tipi di riferimento). == confronta l'identità dell'oggetto, che restituisce false perché sono oggetti diversi.

0

Java 5.0 dispone di boxing e unboxing automatici, il che significa che i wrapper possono essere convertiti implicitamente in primitive e viceversa. Tuttavia, se si confrontano due oggetti Integer, si stanno ancora confrontando due riferimenti e non c'è nulla che possa attivare il boxing/unboxing automatico. In questo caso, il codice scritto in J2SE 1.4 e precedente si interromperebbe.

10

Si noti inoltre che le nuove versioni di cache di Java Integer s nelle -128 a 127 raggio (256 valori), il che significa che:

Integer i1, i2; 

i1 = 127; 
i2 = 127; 
System.out.println(i1 == i2); 

i1 = 128; 
i2 = 128; 
System.out.println(i1 == i2); 

stamperà true e false. (Vedere su ideone)

Morale: Per evitare problemi, utilizzare sempre .equals() quando si confrontano due oggetti.

Potete contare su unboxing quando si utilizza == per confrontare una avvolto primitiva ad una primitiva (ad esempio: Integer con int), ma se si confrontano due Integer s con == che fallirà per le ragioni @ dan04 spiegato.

+0

Interessante! Non userei mai == IRL, ma questo è un esame molto sadico di cui stiamo parlando :) –

+0

Wow, anche 1.4 lo aveva già. Interessante. – EboMike

+1

+1 per il punto molto rilevante. Farò nitpick e sottolineo che è [da -128 a 127] (http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7), sebbene la fonte 1.6 che viene fornita con il Sun JDK mostra loro di giocare con il limite superiore (è sempre almeno 127, però). –

1

No, non penserei che il codice stampato sia vero, e tu hai risposto esattamente a te stesso perché.

Quando == viene usato per confrontare un primitivo ad un involucro, l'involucro sarà scartato e il confronto sarà primitiva a primitiva.

e quindi è andato a confrontare due riferimenti Integer - cioè, ha confrontato l'indirizzo di memoria di i1 e i2. Volevi sia

Integer i1 = 1; 
Integer i2 = new Integer(1); 
System.out.println(i1.equals(i2)); 

O

int i1 = 1; 
Integer i2 = new Integer(1); 
System.out.println(i1 == i2); 
1

Nota che letto male il brano che hai citato. Il brano limita specificamente essa dichiarazione a confronti come questi:

int k = 1; 
Integer l = new Integer(1); 
System.out.println(l == k); 
0

lasciare supporre ha avere un esempio

Quale sarà l'output di questo codice di programma?

public class autoboxing { 
public static void main(String a args) { 
Integer a = new Integer(127); 
Integer b = new Integer(127); 
Integer c = 127; 
Integer d = 127; 
Integer e = new Integer(200); 
Integer f = new Integer(200); 
Integer g = 200; 
Integer h = 200; 
System.out.println((a == b) + ' " + (c =-- d) + " " + (e==f)+ " "+ (g == h)); 

.

Quando si crea un oggetto Integer con un nuovo operatore, viene restituito un nuovo oggetto ogni volta. Quando si confrontano due variabili di riferimento con l'operatore "==", se due variabili di riferimento si riferiscono a due oggetti diversi, l'operatore "==" restituisce false.

Quindi,

(a == b) e (e == f) le espressioni restituisce false. La classe intera memorizza nella cache valori compresi tra -128 e 127.

Quando si confrontano due oggetti Integer con l'operatore "==", se questi due oggetti interi vengono creati con autoboxing, verrà chiamato il metodo value0f (int i).

RISPOSTA: Falso Vero Falso Falso

Di seguito si riporta l'attuazione di tale metodo

public static Integer value0f(int i) { 
if (i >= IntegerCachedow && i <= IntegerCache.high) 
return IntegerCache.cacheli + (-IntegerCachedow)); 
return new Integer(i); 

Da quanto sopra implementazione, di seguito sono le conclusioni

  1. se due oggetti Integer i valori sono compresi tra -128 e 127, questo metodo restituisce gli stessi valori. Quindi (c == d) restituisce true.

  2. Se due valori di oggetti Integer sono al di fuori dell'intervallo da -128 a 127, questo metodo restituisce diversi nuovi oggetti Integer. Così, (g == h) restituisce false

Maggiori dettagli circa il metodo qui: https://stackoverflow.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127

Problemi correlati