2015-11-24 49 views
6

sto paragonando due pezzi di codiceJava - intero boxe - il motivo per cui ritornare vero se dovrebbe restituire false

Integer x = new Integer(0), y; 
y=x; 
x+=0; 
System.out.println(x==y); // prints false 

E

Integer x = 0, y; 
y=x; 
x+=0; 
System.out.println(x==y); // prints true 

non dovrebbero entrambi tornare false? Non è una variabile primitiva e in qualche modo nel secondo codice anche dopo aver aggiunto zero, stampa true. Conosco la boxe (per Integer da -128 a 127), ma perché la boxe funziona nel secondo pezzo di codice e non nel primo?

+1

no, perché "Intero" nell'intervallo di -128 - 127' viene memorizzato nella cache. Nel tuo primo esempio si crea in modo esplicito un nuovo 'Integer', nonostante il fatto che ogni' Integer' nell'intervallo di '-128 - 127' si riferisca allo stesso oggetto. – SomeJavaGuy

+0

Nonostante ciò che altre risposte dicono -128 - 127 non è dogma, è solo una funzionalità di JVM, che può essere ottimizzata su alcune versioni con la proprietà '-Djava.lang.Integer.IntegerCache.high', ei valori predefiniti possono differire notevolmente da Da JVM a JVM, ** Non dovresti mai fare affidamento su questo comportamento! ** Vedi http: // StackOverflow.it/questions/15052216/how-large-is-the-integer-cache –

risposta

16

Non dovrebbero entrambi restituire falso?

La linea

x += 0; 

è lo stesso di

x = Integer.valueOf(x.intValue() + 0); 

in modo da vedere che utilizza la boxe e unboxing per completare le operazioni.


Il secondo esempio utilizza solo la box in modo che funzioni come previsto.

Nel primo esempio, si evita esplicitamente di boxe con

Integer x = new Integer(0); 

Questo costringe a creare un nuovo oggetto che è diverso per l'oggetto in scatola.

Se fai

Integer x = Integer.valueOf(0); 

si comporterà lo stesso del secondo esempio.

+0

Forse se il compilatore fosse abbastanza intelligente, potrebbe forse aver ignorato l'incremento di '0'? – TheLostMind

+0

@VinodMadyalkar sì, tuttavia ha un effetto collaterale come questo. Java è molto riluttante a rompere la compatibilità anche se non ha molto senso IMHO. nota: 'x + = 0f' fa qualcosa per alcuni valori, forse sorprendentemente. –

+0

In realtà ci ho pensato prima di commentare. Ma sicuramente il compilatore può fare cose in casi normali (come nella domanda) :). Questo probabilmente impedirà più istruzioni bytecode – TheLostMind

5

no, perché il numero intero nell'intervallo -128 - 127 viene memorizzato nella cache. Nel primo esempio, si crea in modo esplicito un nuovo numero intero, nonostante il fatto che ogni numero intero nell'intervallo compreso tra -128 - 127 faccia riferimento allo stesso oggetto.

È possibile avvisare questo se si aggiunge qualcosa nel primo esempio. Segnalatemi che questo funzionerà solo nella Integer gamma di -128 - 127

Integer x = new Integer(0), y; 
Integer z = 0; // refers to the cached value. 
y=x; 
x+=0; 
System.out.println(x==z); // This will now print true, since x+=0 will return the cached Integer. 

tuo secondo esempio non funzionerà più lontato se si desidera cambiare il valore x a qualcosa di diverso, per esempio 360

1

Perché,

Numero intero x è un oggetto. Quindi ==, confronta il riferimento e non il valore.

int x non è un oggetto Così ==, confronta il valore

Il codice semplice:

Integer x = new Integer(0), y; 
y=x; 
x+=0; 
System.out.println(x==y); // prints false 
System.out.println(x.equals(y)); // prints true 

int x1, y1; 
x1 = 5; 
y1 = x1; 

System.out.println(x1==y1); // prints true 
System.out.println(((Integer) x1).equals(y1)); //prints true 

E i risultati:

  • falsa
  • vero
  • vero
  • veri

migliori saluti

OK - ho visto la risposta con javap (grazie per la risposta) e ho capito cosa mi manca. Tuttavia, trovo che il pezzo di codice che propongo rimanga interessante.

+1

Penso che tu non abbia capito l'essenza della domanda di Asker. È sorpreso, perché il secondo esempio restituisce il vero. – Michal

3

[update] Utilizzando new Integer(int) è garantito per portare sempre in un nuovo oggetto, mentre Integer.valueOf(int) consente la memorizzazione nella cache di valori deve essere fatto dal compilatore, libreria di classi, o JVM.

Per spiegare che ho scritto sotto il codice e utilizzato lo strumento javap, comando per generare sotto il codice Ho usato javap -c <Classname> che ti dà il codice byte.

Integer x = new Integer(0), y; 
    y=x; 
    x+=0; 
    System.out.println(x==y); // prints false 

enter image description here

Se si vedrà nel codice sopra di esso crea nuovo oggetto con allocatore di memoria dinamica che è new. Ora nel secondo caso come sotto:

Integer x = 0, y; 
    y=x; 
    x+=0; 
    System.out.println(x==y); // prints true 

enter image description here

Come detto da Peter utilizza valueOf metodo che significa che è confrontare stesso oggetto in fase di esecuzione in modo che ritorni true con operatore confronto oggetti (==). Ma nel primo caso si stava creando nuovo oggetto che è evidente in seguito snapshot debug:

enter image description here

Spero che questo aiuta. :)

A proposito, la risposta di Kevin Esche aggiunge anche alla domanda. Poiché si riferisce fondamentalmente all'oggetto memorizzato nella cache, provare a correlarlo in caso di String. Se si utilizza new String("some_string"), verrà creato un nuovo oggetto diverso se disponibile che utilizzerà da string pool. E ricorda che stai usando classi wrapper non primitive.