Perché 128 == 128 falso, ma 127 == 127 è vero quando si confrontano i wrapper Integer in Java?
-
19-09-2019 - |
Domanda
class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}
Output:
false
class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}
Output:
true
Nota: I numeri tra -128 e 127 sono vere
.Soluzione
Quando si compila un numero letterale in Java e assegnarlo a un numero intero (I
capitale) il compilatore emette:
Integer b2 =Integer.valueOf(127)
Questa riga di codice viene generato anche quando si utilizza autoboxing.
valueOf
è implementata in modo tale che alcuni numeri sono "riuniti", e restituisce la stessa istanza per valori inferiori a 128.
Dal codice sorgente di Java 1.6, la linea 621:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
Il valore del high
può essere configurato per un altro valore, con la proprietà di sistema.
-Djava.lang.Integer.IntegerCache.high = 999
Se si esegue il programma con quella proprietà di sistema, il risultato sarà vero!
L'ovvia conclusione: mai fare affidamento su due riferimenti sono identici, li confronta sempre con metodo .equals()
Così b2.equals(b3)
stamperà vero per tutti i valori logicamente uguali di B2, B3.
Si noti che la cache Integer
non è lì per motivi di prestazioni, ma piuttosto di conformarsi al JLS, sezione 5.1.7 ; identità oggetto deve essere dato per i valori da -128 a 127 compreso.
Integer # valueOf (int) documenta anche questo comportamento:
questo metodo rischia di produrre significativamente migliore spazio e nel tempo le prestazioni mettendo in cache i valori frequentemente richiesti. Questo metodo sarà sempre in cache i valori nella gamma da -128 a 127, comprensivo, e può memorizzare nella cache altri valori al di fuori di questo intervallo.
Altri suggerimenti
Autoboxing memorizza nella cache da -128 a 127. Questo è specificato nella JLS ( 5.1.7 ).
Se il valore p di essere inscatolato è vero, falso, un byte, un char nel campo \ u0000 a \ u007F, o un numero di int o cortocircuito tra -128 e 127, poi lasciate r1 e r2 essere i risultati di qualsiasi due conversioni boxe di p. E 'sempre il caso che r1 == r2.
Una semplice regola da ricordare quando si tratta di oggetti è - uso .equals
se si desidera controllare se i due oggetti sono "uguali", l'uso ==
quando si vuole vedere se puntano alla stessa istanza
Utilizzare tipi di dati primitivi, int, produrrebbe vero in entrambi i casi, i risultati attesi.
Tuttavia, dal momento che si sta utilizzando Integer oggetti l'operatore == ha un significato diverso.
Nel contesto di oggetti, == controlla se le variabili si riferiscono allo stesso riferimento all'oggetto.
Per confrontare il valore degli oggetti è necessario utilizzare l'equals (metodo) Per es.
b2.equals(b1)
che indicano se b2 è inferiore b1, maggiore o uguale a (controllare le API per i dettagli)
E 'l'ottimizzazione della memoria in Java correlati.
Per salvare sulla memoria, Java 'riutilizza' tutti gli oggetti wrapper valori la cui rientrano nei seguenti intervalli:
Tutti i valori booleani (vero e falso)
Tutti i valori di byte
Tutti i valori di carattere da \ u0000 a \ u007F (cioè da 0 a 127 in decimale)
Tutti i valori brevi e intero da -128 a 127.
Dai un'occhiata al Integer.java, se il valore è compreso tra -128 e 127, userà la piscina nella cache, in modo da (Integer) 1 == (Integer) 1
mentre (Integer) 222 != (Integer) 222
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
ho scritto quanto segue come questo problema non è solo specifico per intero. La mia conclusione è che il più delle volte, se si utilizza l'API in modo non corretto, si vede davanzale comportamento non corretto. Utilizzare correttamente e si dovrebbe vedere il comportamento corretto:
public static void main (String[] args) {
Byte b1=127;
Byte b2=127;
Short s1=127; //incorrect should use Byte
Short s2=127; //incorrect should use Byte
Short s3=128;
Short s4=128;
Integer i1=127; //incorrect should use Byte
Integer i2=127; //incorrect should use Byte
Integer i3=128;
Integer i4=128;
Integer i5=32767; //incorrect should use Short
Integer i6=32767; //incorrect should use Short
Long l1=127L; //incorrect should use Byte
Long l2=127L; //incorrect should use Byte
Long l3=13267L; //incorrect should use Short
Long l4=32767L; //incorrect should use Short
Long l5=2147483647L; //incorrect should use Integer
Long l6=2147483647L; //incorrect should use Integer
Long l7=2147483648L;
Long l8=2147483648L;
System.out.print(b1==b2); //true (incorrect) Used API correctly
System.out.print(s1==s2); //true (incorrect) Used API incorrectly
System.out.print(i1==i2); //true (incorrect) Used API incorrectly
System.out.print(l1==l2); //true (incorrect) Used API incorrectly
System.out.print(s3==s4); //false (correct) Used API correctly
System.out.print(i3==i4); //false (correct) Used API correctly
System.out.print(i5==i6); //false (correct) Used API correctly
System.out.print(l3==l4); //false (correct) Used API correctly
System.out.print(l7==l8); //false (correct) Used API correctly
System.out.print(l5==l6); //false (correct) Used API incorrectly
}