2013-02-25 16 views
9

Qualcuno ha postulato in alcuni thread del forum che molte persone e anche esperti sviluppatori Java non avrebbero compreso la seguente tranquillità del codice Java.Comportamento sconcertante di == dopo la post-conversione

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

Come persona con un certo interesse per Java, ho dato il mio pensiero e sono arrivato al seguente risultato.

System.out.println(i1++ == i2++); 
// True, since we first check for equality and increment both variables afterwards. 

System.out.println(i1 == i2); 
// True again, since both variables are already incremented and have the value 128 

Eclipse mi dice il contrario. La prima riga è vera e la seconda è falsa.

Gradirei davvero una spiegazione.

Seconda domanda. Questo è Java specifico o questo esempio vale anche per i linguaggi basati su C?

+0

try 'i1.equals (i2)' – vikingsteve

+8

http://stackoverflow.com/questions/5117132/integer-wrapper-objects-share-the-same-instances-only-within-the-value-127 –

+0

Questo la domanda è estremamente simile a quella pubblicata da @DominikKunicki –

risposta

14
Integer i1 = 127; 
Integer i2 = 127; 
System.out.println(i1++ == i2++); 
// here i1 and i2 are still 127 as you expected thus true 
System.out.println(i1 == i2); 
// here i1 and i2 are 128 which are equal but not cached 
    (caching range is -128 to 127), 

Nel caso 2 Se si utilizza equals() che sarebbe tornare vero come == operatore per gli interi funziona solo per i valori memorizzati nella cache. come 128 è fuori portata cache non verranno memorizzate i valori sopra 128, così youhave usare equals() metodo per controllare se due istanze interi sopra 127 sono vero

TEST:

Integer i1 = 126; 
    Integer i2 = 126; 
    System.out.println(i1++ == i2++);// true 
    System.out.println(i1 == i2); //true 



Integer i1 = 126; 
     Integer i2 = 126; 
     System.out.println(i1++ == i2++);// true 
     System.out.println(i1.equals(i2)); //true 

    Integer i1 = 128; 
     Integer i2 = 128; 
     System.out.println(i1++ == i2++);// false 
     System.out.println(i1==i2); //false 

    Integer i1 = 128; 
     Integer i2 = 128; 
     System.out.println(i1++.equals(i2++));// true 
     System.out.println(i1.equals(i2)); //true 
+4

Come nota di cautela, ritengo che l'intervallo di memorizzazione nella cache sia specifico dell'implementazione JVM e non sia parte del JLS. Pertanto, non è garantito che questo comportamento sia coerente tra le JVM. –

+1

@ChrisKnight Non è specifico dell'implementazione, come nelle specifiche. [Paragrafo 5.1.7] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7) afferma: * "Se il valore p inserito è [...] un numero int o un numero breve compreso tra -128 e 127 (incluso), quindi r1 e r2 sono i risultati di due conversioni di boxing pari a p. È sempre il caso che r1 == r2. "* –

+1

@ Mattias Buelens - Abbiamo ragione entrambi.Per chiarire, da -128 a 127 (incluso) è garantito. Tuttavia, JVM può estendere questo intervallo memorizzato nella cache. Ulteriore testo nel suo riferimento: "Meno implementazioni con memoria limitata potrebbero, ad esempio, memorizzare nella cache tutti i valori char e short, nonché i valori int e long nell'intervallo da -32K a +32K.". –

1

Come spiegato questo è dovuto a Integer caching. Per divertimento, è possibile eseguire il programma con la seguente opzione JVM:

-XX:AutoBoxCacheMax=128 

e sarà stampare vero due volte (opzione disponibile su hostpot 7 - non necessariamente su altre JVM).

Nota che:

  • questo è JVM specifica
  • il comportamento modificato è conforme alla JLS che dice che tutti i valori compresi tra -128 e +127 devono essere memorizzati nella cache, ma dice anche che altri valori può essere memorizzato nella cache.

Linea di fondo: la seconda istruzione print non è definito in Java e può stampare vero o falso a seconda dell'implementazione JVM e/o le opzioni JVM utilizzato.

+0

L'ho appena eseguito con quel parametro e ha ancora False. –

+0

@AleksG Funziona con la versione di hotspot 7u11. – assylias

+0

Con OpenJDK su 64-bit Linux non è così. –