Confronto dei valori Long in scatola 127 e 128


111

Voglio confrontare due valori di oggetti lunghi usando le ifcondizioni. Quando questi valori sono inferiori a 128 , la ifcondizione funziona correttamente, ma quando sono maggiori o uguali a 128 , il confronto non riesce.

Esempio:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

Il confronto sul codice sopra funziona correttamente, ma fallisce nel codice seguente:

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

Perché c'è un problema nel confrontare le variabili Long con valori maggiori di 127 ? Se i tipi di dati delle variabili vengono modificati in primitive lunghe , i confronti funzionano per tutti i casi.

Risposte:


212

TL; DR

Java memorizza istanze Integer boxed da -128a 127. Poiché stai utilizzando ==per confrontare i riferimenti agli oggetti invece dei valori , solo gli oggetti memorizzati nella cache corrisponderanno. O lavora con longvalori primitivi unboxed o usa .equals()per confrontare i tuoi Longoggetti.

Versione lunga (gioco di parole)

Perché c'è un problema nel confrontare la variabile Long con un valore maggiore di 127? Se il tipo di dati della variabile precedente è primitivo (lungo), il codice funziona per tutti i valori.

Java memorizza nella cache istanze di oggetti Integer compresi tra -128 e 127 . Detto ciò:

  • Se si imposta a N variabili lunghe il valore 127( memorizzato nella cache ), la stessa istanza di oggetto verrà puntata da tutti i riferimenti. (N variabili, 1 istanza)
  • Se imposti a N variabili lunghe il valore 128( non memorizzato nella cache ), avrai un'istanza di oggetto puntata da ogni riferimento. (N variabili, N istanze)

Ecco perché questo:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2);

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4);

Emette questo:

vero
falso

Per il valore 127L , poiché entrambi i riferimenti (val1 e val2) puntano alla stessa istanza di oggetto in memoria (memorizzata nella cache), restituisce true.

D'altra parte, per il valore 128 , poiché non vi è alcuna istanza per esso memorizzato nella cache, ne viene creata una nuova per eventuali nuove assegnazioni per i valori boxed, risultando in due istanze diverse (indicate da val3 e val4) e restituendo falseil confronto tra loro.

Ciò accade solo perché stai confrontando due Long riferimenti a oggetti , non longvalori primitivi, con l' ==operatore. Se non fosse per questo meccanismo di cache, questi confronti fallirebbero sempre , quindi il vero problema qui è confrontare i valori boxed con l' ==operatore.

La modifica di queste variabili in longtipi primitivi impedirà che ciò accada, ma nel caso in cui sia necessario mantenere il codice utilizzando Longoggetti, è possibile effettuare questi confronti in sicurezza con i seguenti approcci:

System.out.println(val3.equals(val4));                     // true
System.out.println(val3.longValue() == val4.longValue());  // true
System.out.println((long)val3 == (long)val4);              // true

(È necessario un corretto controllo dello zero, anche per le fusioni)

IMO , è sempre una buona idea attenersi ai metodi .equals () quando si ha a che fare con i confronti di oggetti.

Link di riferimento:


15

Java memorizza nella cache i valori primitivi da -128 a 127 . Quando confrontiamo due oggetti Long , java digita internamente il cast al valore primitivo e lo confronta. Ma sopra 127 l'oggetto Lungo non avrà il tipo casta. Java memorizza nella cache l'output con il metodo .valueOf () .

Questo caching funziona per Byte, Short, Long da -128 a 127. Per il caching Integer funziona Da -128 a java.lang.Integer.IntegerCache.high o 127, a seconda di quale dei due è più grande. (Possiamo impostare il valore di livello superiore fino a cui dovrebbe essere memorizzato nella cache utilizzando java.lang.Integer.IntegerCache.high).

 For example:
    If we set java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

Gli oggetti Float e Double non vengono mai memorizzati nella cache.

Il personaggio riceverà la cache da 0 a 127

Stai confrontando due oggetti. quindi == l' operatore verificherà l'uguaglianza dei riferimenti agli oggetti. Ci sono i seguenti modi per farlo.

1) digita cast entrambi gli oggetti in valori primitivi e confronta

    (long)val3 == (long)val4

2) leggere il valore dell'oggetto e confrontare

    val3.longValue() == val4.longValue()

3) Utilizzare il metodo equals () sul confronto degli oggetti.

    val3.equals(val4);  

14

num1e num2sono oggetti lunghi. Dovresti equals()usarli per confrontarli. ==il confronto potrebbe funzionare a volte a causa del modo in cui JVM inscatola le primitive, ma non dipende da esso.

if (num1.equals(num1))
{
 //code
}

1
Questo (che è meglio) o confronta il valore restituito di .longValue().
Giulio Franco

4

Confrontando le non primitive (note anche come oggetti) in Java con il ==loro riferimento invece dei loro valori. Longè una classe e quindi i Longvalori sono Oggetti.

Il problema è che gli sviluppatori Java volevano che le persone Longusassero come usavano longper fornire compatibilità, il che ha portato al concetto di autoboxing, che è essenzialmente la caratteristica, che i longvalori verranno modificati in Long-Objects e viceversa secondo necessità. Il comportamento dell'autoboxing non è però sempre prevedibile, in quanto non è completamente specificato.

Quindi, per sicurezza e per avere risultati prevedibili, usa sempre .equals()per confrontare gli oggetti e non fare affidamento sull'autoboxing in questo caso:

Long num1 = 127, num2 = 127;
if(num1.equals(num2)) { iWillBeExecutedAlways(); }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.