2010-06-04 14 views
64

Stavo usando Sonar per rendere il mio codice più pulito, e ha sottolineato che sto usando new Integer(1) anziché Integer.valueOf(1). Perché sembra che valueOf non istanzia un nuovo oggetto, quindi è più adatto alla memoria. In che modo valueOf non crea un'istanza di un nuovo oggetto? Come funziona? È vero per tutti gli interi?Nuovo numero intero vs valoreDi

+13

Nota: se si utilizza autoboxing, utilizza Integer. valueOf (int) per te. –

risposta

66

Integer.valueOf implementa una cache per i valori da -128 a +127. Vedere l'ultimo paragrafo della Specifica del linguaggio Java, sezione 5.1.7, che spiega i requisiti per il pugilato (solitamente implementato in termini dei metodi .valueOf).

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7

+0

lo so, era da qualche parte nel unboxing, ma ho potuto trovare la sezione. grazie – LB40

+1

Questa sezione non dice nulla di esplicativo su valueOf. La boxe viene solitamente implementata in termini di valoreOf, ma non è necessario. Inoltre, è consentito anche memorizzare i valori al di fuori di tale intervallo. Questo è solo un intervallo minimo per il pugilato. –

+21

Solo per completezza, si noti inoltre che su Sun VM, il valore massimo della cache è configurabile dall'utente usando '-XX: AutoBoxCacheMax = ...' –

26

Dal JavaDoc:

public static Integer valueOf (int i) restituisce un'istanza numero intero che rappresenta il valore int specificato. Se non è richiesta una nuova istanza Integer, questo metodo deve essere generalmente utilizzato in preferenza rispetto al costruttore Integer (int), poiché è probabile che questo metodo produca prestazioni significativamente migliori in termini di spazio e tempo memorizzando nella cache i valori richiesti di frequente.

ValueOf viene utilizzato per Generaly autoboxing e quindi (quando usato per autoboxing) memorizza nella cache a valori minimi da -128 a 127 di seguire le specifiche autoboxing.

Ecco l'implementazione valueOf per Sun JVM 1.5.? Dai un'occhiata all'intera classe per vedere come viene inizializzata la cache.

public static Integer valueOf(int i) { 
    final int offset = 128; 
    if (i >= -128 && i <= 127) { // must cache 
     return IntegerCache.cache[i + offset]; 
    } 
    return new Integer(i); 
} 
2

stanno spingendo l'uso valueOf() invece di new Integer() quindi il metodo valueOf() fa per voi, e memorizza nella cache il valore nel caso in cui si desidera ottenere lo stesso numero di nuovo in futuro. In tal caso, il metodo non instacete il nuovo Integer, ma vi darà quello memorizzato nella cache, cosa renderà la "creazione" del nuovo intero molto più veloce e processo di facile memorizzazione ..

In questo modo potresti causare un sacco di problemi se sei un programmatore java inesperto dal momento che concluderai che Integer.valueOf(342)==Integer.valueOf(342), perché potresti (o meno) avere lo stesso puntatore per due Interi, e probabilmente lo eserciterai in un modo, diciamo, hai imparato in C#, in modo che ti mostrerà bug di tanto in tanto e non saprai come & da dove provengono ...

2

Dal codice sorgente java.lang.Integer. La cache dei numeri interi è configurabile. Per configurare la dimensione della cache Integer diversa da Sun, è necessario utilizzare la proprietà System java.lang.Integer.IntegerCache.high come da codice sorgente.

/** 
* Cache to support the object identity semantics of autoboxing for values between 
* -128 and 127 (inclusive) as required by JLS. 
* 
* The cache is initialized on first usage. During VM initialization the 
* getAndRemoveCacheProperties method may be used to get and remove any system 
* properites that configure the cache size. At this time, the size of the 
* cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>. 
*/ 

// value of java.lang.Integer.IntegerCache.high property (obtained during VM init) 
private static String integerCacheHighPropValue; 

static void getAndRemoveCacheProperties() { 
    if (!sun.misc.VM.isBooted()) { 
     Properties props = System.getProperties(); 
     integerCacheHighPropValue = 
      (String)props.remove("java.lang.Integer.IntegerCache.high"); 
     if (integerCacheHighPropValue != null) 
      System.setProperties(props); // remove from system props 
    } 
} 

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() {} 
} 

Da java.lang.Short, java.lang.Byte e java.lang.Long crea una cache di 127 a -128

private static class LongCache { 
    private LongCache() { 
    } 

    static final Long cache[] = new Long[-(-128) + 127 + 1]; 

    static { 
     for (int i = 0; i < cache.length; i++) 
      cache[i] = new Long(i - 128); 
    } 
} 

private static class ShortCache { 
    private ShortCache() { 
    } 

    static final Short cache[] = new Short[-(-128) + 127 + 1]; 

    static { 
     for (int i = 0; i < cache.length; i++) 
      cache[i] = new Short((short) (i - 128)); 
    } 
} 

private static class ByteCache { 
    private ByteCache() { 
    } 

    static final Byte cache[] = new Byte[-(-128) + 127 + 1]; 

    static { 
     for (int i = 0; i < cache.length; i++) 
      cache[i] = new Byte((byte) (i - 128)); 
    } 
}