2013-02-22 7 views
23

Perché numero intero "=" L'operatore non funziona per 128 e dopo i valori Integer? Qualcuno può spiegare questa situazione?Perché l'operatore uguale funziona per il valore intero fino al numero 128?

Questo è il mio ambiente Java: versione java "1.6.0_37"

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

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

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"); 
     } 
    } 

Una parte di output di 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!

+0

da -128 a 127 –

+0

'=' è l'operatore di assegnazione e non lo si utilizza nel codice di esempio corrente; intendevi '=='? – geoffspear

risposta

19

Check out the source code of Integer. Puoi vedere la memorizzazione nella cache dei valori lì.

Il caching si verifica solo se si utilizza Integer.valueOf(int), non se si utilizza new Integer(int). Il Autoboxing utilizzato da voi utilizza Integer.valueOf

Secondo il JLS, si può sempre contare sul fatto che per valori compresi tra -128 e 127, si ottiene gli oggetti Integer identici dopo autoboxing, e su alcune implementazioni si potrebbe ottenere oggetti identici anche per valori più alti.

In realtà in Java 7 (e penso nelle versioni più recenti di Java 6), lo implementation della classe IntegerCache è stato modificato e il limite superiore non è più codificato, ma è configurabile tramite la proprietà "java.lang". Integer.IntegerCache.high ", 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 JLS garantisce ancora solo fino 127:

Idealmente, pugilato un valore di base determinato p, sarebbe sempre dare un riferimento identici. 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 consente alcuna ipotesi sull'identità 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 sarà quello desiderato, senza imporre una penalità di prestazioni eccessive, in particolare 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.

+0

+1 Sarebbe bello se colleghi il codice sorgente alla tua risposta :) – PermGenError

6

secondo le specifiche del linguaggio Java:

Se il valore p essere inscatolato è vero, falso, un byte, un char nella gamma \ u0000 a \ u007F, o un int o un numero breve tra - 128 e 127, quindi lascia che r1 e r2 siano i risultati di due conversioni di boxing di p. È sempre che r1 == r2.

JLS Boxing Conversions

Refer to this article for more information on int caching

+5

Questa risposta è sbagliata, non deve fare nulla con l'hotspot jvm, la memorizzazione nella cache è implementata nel codice sorgente di Integer, – lbalazscs

+1

@lbalazscs, per quanto ne so i valori che sono memorizzati nella cache sono dipendenti da jvm. Penso che questo caching sia specificato nelle specifiche del linguaggio java, ma i valori da memorizzare nella cache non sono specificati. Questo è il motivo per cui ho menzionato l'hotspot jvm. Non è corretto? –

+3

Non è corretto. Per esempio, non dare un'occhiata al codice sorgente di 'java.lang.Integer'. –

2

Uso .equals() invece di ==.

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

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

Integer è una classe wrapper per int.

Integer != Integer confronta il riferimento oggetto reale, dove int != int confronterà i valori.

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

Se al di fuori di tale intervallo, verranno creati oggetti separati in modo che il riferimento sia diverso.

Per risolvere il problema:

  • rendere i tipi int o
  • Fusioni i tipi di int o
  • Usa .equals()
3

L'oggetto 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 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 si dovrebbe usare valueOf invece di new Integer. Autoboxing utilizza questa cache.

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

utilizzando == non è una buona idea, l'uso è uguale per confrontare i valori.

1

A seconda di come si ottiene il Integer casi, potrebbe non funzionare per qualsiasi valore:

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

stampe

false 

operandi Questo perché l'operatore == applicato al riferimento tipizzato non ha nulla fare con il valore che rappresentano gli operandi.

Problemi correlati