Perché l’operatore uguale funziona per il valore intero fino al numero 128?

Perché l’operatore “=” intero non funziona per 128 e dopo valori interi? Qualcuno può spiegare questa situazione?

Questo è il mio ambiente Java: versione java “1.6.0_37”

Java (TM) SE Runtime Environment (build 1.6.0_37-b06)

VM server Java HotSpot (TM) a 64 bit (build 20.12-b01, modalità mista)

Codice d’esempio:

    Integer a; Integer b; a = 129; b = 129; for (int i = 0; i < 200; i++) { a = i; b = i; if (a != b) { System.out.println("Value:"+ i + " - Different values"); } else { System.out.println("Value"+ i + " Same values"); } } 

    Alcune parti dell’output della console:

     Value:124 - Same values Value:125 - Same values Value:126 - Same values Value:127 - Same values Value:128 - Different values Value:129 - Different values Value:130 - Different values Value:131 - Different values Value:132 - Different values 

    Grazie!

    Controlla il codice sorgente di Integer . Puoi vedere la memorizzazione nella cache dei valori lì.

    La memorizzazione nella cache avviene solo se si utilizza Integer.valueOf(int) , non se si utilizza il new Integer(int) . L’autoboxing utilizzato dall’utente utilizza Integer.valueOf

    Secondo JLS , puoi sempre contare sul fatto che per valori compresi tra -128 e 127, ottieni gli oggetti interi identici dopo l’autoboxing e su alcune implementazioni potresti ottenere oggetti identici anche per valori più alti.

    In realtà in Java 7 (e penso nelle versioni più recenti di Java 6), l’ implementazione della class IntegerCache è cambiata e il limite superiore non è più codificato, ma è configurabile tramite la proprietà “java.lang.Integer.IntegerCache. alto “, quindi se si esegue il programma con il parametro VM -Djava.lang.Integer.IntegerCache.high=1000 , si ottiene” Stessi valori “per tutti i valori.

    Ma il JLS lo garantisce ancora fino al 127:

    Idealmente, inscatolare un dato valore primitivo p, darebbe sempre un riferimento identico. In pratica, questo potrebbe non essere fattibile utilizzando le tecniche di implementazione esistenti. Le regole di cui sopra sono un compromesso pragmatico. La clausola finale sopra richiede che determinati valori comuni siano sempre racchiusi in oggetti indistinguibili. L’implementazione può memorizzarli in cache, pigramente o impazientemente.

    Per altri valori, questa formulazione non ammette alcuna ipotesi sull’identity framework dei valori inseriti nella parte del programmatore. Ciò consentirebbe (ma non richiederà) la condivisione di alcuni o tutti questi riferimenti.

    Ciò garantisce che, nei casi più comuni, il comportamento sia quello desiderato, senza imporre una penalità di prestazioni eccessive, specialmente su dispositivi di piccole dimensioni. Ad esempio, meno implementazioni a memoria limitata potrebbero memorizzare nella cache tutti i caratteri e i corti, nonché interi e lunghi nell’intervallo di -32K – + 32K.

    Integer è una class wrapper per int .

    Integer != Integer confronta il riferimento object attuale, dove int != int confronta i valori.

    Come già detto, i valori da -128 a 127 vengono memorizzati nella cache, quindi gli stessi oggetti vengono restituiti per quelli.

    Se all’esterno di tale intervallo, verranno creati oggetti separati in modo che il riferimento sia diverso.

    Per risolverlo:

    • Crea i tipi int o
    • Trasmetti i tipi a int o
    • Usa .equals()

    Secondo le specifiche della lingua Java:

    Se il valore p in box è true, false, un byte, un char nell’intervallo da \ u0000 a \ u007f o un numero int o short compreso tra -128 e 127, allora r1 e r2 saranno i risultati di due conversioni di boxing di p. È sempre il caso che r1 == r2.

    Conversioni di boxe JLS

    Fare riferimento a questo articolo per ulteriori informazioni sulla memorizzazione nella cache int

    L’object Integer ha un meccanismo di cache interna:

     private static class IntegerCache { static final int high; static final Integer cache[]; static { final int low = -128; // high value may be configured by property int h = 127; if (integerCacheHighPropValue != null) { // Use Long.decode here to avoid invoking methods that // require Integer's autoboxing cache to be initialized int i = Long.decode(integerCacheHighPropValue).intValue(); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - -low); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} } 

    Vedi anche il metodo valueOf:

     public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); } 

    Questo è il motivo per cui dovresti usare valueOf invece del new Integer . Autoboxing utilizza questa cache.

    Vedi anche questo post: https://effective-java.com/2010/01/java-performance-tuning-with-maximizing-integer-valueofint/

    Usare == non è una buona idea, usa uguaglianza per confrontare i valori.

    Usa .equals() invece di == .

    I valori interi vengono memorizzati nella cache solo per numeri compresi tra -127 e 128, poiché vengono utilizzati più spesso.

     if (a.equals(b)) { ... } 

    A seconda di come ottieni le istanze di Integer , potrebbe non funzionare per qualsiasi valore:

     System.out.println(new Integer(1) == new Integer(1)); 

    stampe

     false 

    Questo perché l’operatore == applicato agli operandi digitati come riferimento non ha nulla a che fare con il valore rappresentato da tali operandi.

    È perché la logica di implementazione della class Integer . Ha preparato oggetti per numeri fino a 128. Puoi controllare http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Integer.java source of open -jdk per esempio (cerca cache []).
    Fondamentalmente gli oggetti non dovrebbero essere confrontati usando == , con una eccezione a Enums.