Comportamento incoerente su Java ==
Domanda
Considera questo codice:
class test {
public static void main(String[] args) {
test inst_test = new test();
int i1 = 2000;
int i2 = 2000;
int i3 = 2;
int i4 = 2;
Integer Ithree = new Integer(2); // 1
Integer Ifour = new Integer(2); // 2
System.out.println( Ithree == Ifour );
inst_test.method( i3 , i4 );
inst_test.method( i1 , i2 );
}
public void method( Integer i , Integer eye ) {
System.out.println(i == eye );
}
}
Stampa:
false
true
false
Capisco il primo false
, l'operatore == controlla solo se due riferimenti stanno lavorando sullo stesso oggetto, cosa che in questo caso non è possibile.
Il seguente true
E false
farmi grattare la testa.Perché Java dovrebbe prendere in considerazione i3
E i4
uguale ma i1
E i2
diverso?Entrambi sono stati incapsulati in Integer, non dovrebbero Entrambi valutare come falso?C’è una ragione pratica per questa incoerenza?
Soluzione
Autoboxing di primitive in oggetti (come in uso nel proprio chiamate a method
utilizza una cache di piccoli valori. Dal sezione Java Language Specification 5.1.7 :
Se il valore p essere inscatolato è vero, falso, un byte, un char nella gamma \ U0000 a \ u007F, o un int o corto numero compreso tra -128 e 127, poi lasciare r1 e r2 essere i risultati di due qualsiasi conversioni boxe di p. E 'sempre il caso che r1 == r2.
La parte discussione della specifica immediatamente successivo a quello è interessante anche. In particolare una JVM può memorizzare nella cache più valori se si vuole - non si può essere sicuri dei risultati di fare:
Integer i1 = 129;
Integer i2 = 129;
boolean b = (i1 == i2);
Altri suggerimenti
Quando autoboxing, interi fra -128 e 127 vengono memorizzati nella cache, e lo stesso oggetto involucro viene restituito. Lo stesso con valori booleani e valori char tra \ u0000 e \ u007F
Questo è ciò che si ottiene la maggior parte del tempo, tuttavia, dipende sull'attuazione JVM.
Questo perché la boxe rende interi di sotto di un certo valore (128, credo) si riferiscono a qualche oggetto precostruito, e valori più elevati per i nuovi oggetti.
usi autoboxing Integer.valueOf (i) , non new Integer (i), per costruire un oggetto della classe Integer.
Mentre gli altri hanno detto, valueOf () utilizza una cache, per lo più per l'efficienza dello spazio.
Non usare == sui tipi di riferimento, è quasi sempre un errore.
La classe intera contiene una cache di alcune istanze utilizzate di frequente.L'intervallo di valori generalmente varia da JVM a JVM (a volte è anche configurabile) ma in generale il codice rilevante è qualcosa del tipo:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
(codice da sole JDK 1.6)
questo è come l'internamento di stringhe, poiché risparmia memoria e consente l'uguaglianza dei test utilizzando un riferimento (ad es. == al posto di equivale)
Direi che l'involucro cerca di minimizzare il numero di interi oggetti e crea solo un oggetto che rappresenta 2 anche salvare la memoria.
Basta ricordarsi di non usare mai == sugli oggetti non si sa mai cosa succede.
Autoboxing utilizzare alcuni meccanismo di caching. Di solito non si dovrebbe mai fare affidamento su ==
, utilizzare sempre equals
per controllare l'uguaglianza.