2010-03-23 17 views
10
Integer i = 127; 
Integer j = 127; 
System.out.println(i == j); 
System.out.println(i.equals(j)); 

Integer i1 = 128; 
Integer j1 = 128; 
System.out.println(i1 == j1); 
System.out.println(i1.equals(j1)); 

Non capisco perché non si stampa "vero, vero, vero, vero". per favore dare una risposta?Il seguente codice stampa "true, true, false, true". Non dovrebbe essere "vero, vero, vero, vero"?

+2

una tale domanda specifica, hmm, sospettoso – Will

+1

@Will Ho visto la stessa domanda in un libro SCJP –

+1

Scommetto che restituisce falso, vero, falso, vero invece di vero, vero, falso, vero –

risposta

29

Quando si utilizza ==, si sta confrontando le istanze di oggetti per l'uguaglianza.

La ragione per cui i primi due casi sono uguali è che si è creato il Integers utilizzando autoboxing (piuttosto che chiamare new Integer(127)), e il Java Language Specification §5.1.7 richiede che Integers tra -128 e 127 sono memorizzati nella cache.

Implementazioni can cache più valori ma non richiesti; apparentemente la JVM che si sta utilizzando non memorizza nella cache 128. Questo è il caso di Sun Java 6.

5

L'intero è una classe. Se digiti il ​​nuovo numero intero(), crei un nuovo oggetto. Quindi io, j, i1 e j1 sono tutti oggetti diversi. Se usi == è vero solo sullo stesso oggetto. Per i numeri interi minori di 128, la JVM usa sempre lo stesso oggetto, in modo tale che le uscite siano vere.

4

No non dovrebbe:

Integer i1 = 128; 
Integer j1 = 128; 

Autoboxing provoca due oggetti Integer distinti da creare nella realizzazione di Java che si sta utilizzando.

Se i valori interi erano compresi nell'intervallo compreso tra -128 e 127, il JLS indica che verrà utilizzato lo stesso oggetto intero; vedi JLS 1.5.7. Tuttavia, il JLS fa non richiede che i1 e i2 debbano avere valori diversi al di fuori di tale intervallo. Effettivamente la seguente discussione nel JLS dice questo:

Idealmente, il pugilato di 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 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

Come si scrive 2 in inglese? –

+0

@PP - deve essere dopo il momento di coricarsi :-) –

+0

Se ricordo male, Sun Java 7 avrà una cache Integer configurabile. Penso che in particolare aiuti su alcuni benchmark. –

9

solo per aggiungere a tutte le altre risposte corrette, date un'occhiata al source code al fine di comprendere appieno ciò che sta dicendo @mmyers:

584  /** 
    585  * Returns an {@code Integer} instance representing the specified 
    586  * {@code int} value. If a new {@code Integer} instance is not 
    587  * required, this method should generally be used in preference to 
    588  * the constructor {@link #Integer(int)}, as this method is likely 
    589  * to yield significantly better space and time performance by 
    590  * caching frequently requested values. 
    591  * 
    592  * @param i an {@code int} value. 
    593  * @return an {@code Integer} instance representing {@code i}. 
    594  * @since 1.5 
    595  */ 
    596  public static Integer valueOf(int i) { 
    597   final int offset = 128; 
    598   if (i >= -128 && i <= 127) { // must cache 
    599    return IntegerCache.cache[i + offset]; 
    600   } 
    601   return new Integer(i); 
    602  } 
+2

Devi anche sapere che 'Integer i = x' è compilato internamente a' Integer.valueOf (x) ', che è. –

+0

Grazie, sentito che mancava qualcosa. – Tom

Problemi correlati