2010-06-04 17 views
64

Użyłem Sonar, aby mój kod był czysty, i wskazałem, że używam new Integer(1) zamiast Integer.valueOf(1). Ponieważ wydaje się, że valueOf nie tworzy instancji nowego obiektu, więc jest bardziej przyjazny dla pamięci. W jaki sposób valueOf nie utworzyć instancji nowego obiektu? Jak to działa? Czy to prawda w przypadku wszystkich liczb całkowitych?Nowy Integer vs valueOf

+13

Uwaga: jeśli używasz autoboxing, używa Integer. valueOf (int) dla ciebie. –

Odpowiedz

66

Integer.valueOf implementuje pamięć podręczną dla wartości od -128 do +127. Zobacz ostatni akapit Specyfikacji Języka Java, rozdział 5.1.7, w której objaśniono wymagania dotyczące boksu (zwykle implementowane w kategoriach metod .valueOf).

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

+0

Wiem, to było gdzieś w rozpakowaniu, ale mogłem znaleźć sekcję. dzięki – LB40

+1

Ta sekcja nie mówi nic jawnego o valueOf. Boks jest zwykle realizowany pod kątem valueOf, ale nie jest to wymagane. Dozwolone jest również buforowanie wartości poza tym zakresem. To tylko minimalny zakres dla boksu. –

+21

Dla kompletności należy również zauważyć, że w maszynach wirtualnych Sun maksymalna wartość pamięci podręcznej jest konfigurowalna przez użytkownika za pomocą '-XX: AutoBoxCacheMax = ...' –

26

Z JavaDoc:

public static Integer valueOf (int i) Zwraca instancję całkowitą reprezentującą określoną wartość int. Jeśli nowa instancja Integer nie jest wymagana, ta metoda powinna być generalnie stosowana w stosunku do konstruktora Integer (int), ponieważ metoda ta prawdopodobnie przyniesie znacznie lepszą wydajność w przestrzeni i czasie poprzez buforowanie często żądanych wartości.

ValueOf jest Generaly stosowane do autoboxing i dlatego (gdy stosowane do autoboxing) buforuje przynajmniej wartości od -128 do 127, aby po określeniu autoboxing. Jest to implementacja valueOf dla Sun JVM 1.5. Spójrz na całą klasę, aby zobaczyć, jak inicjowana jest pamięć podręczna.

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

oni naciskają na użycie valueOf() zamiast new Integer() więc metoda valueOf() zrobi to za ciebie, i buforuje wartość w przypadku, gdy chcesz uzyskać ten sam numer ponownie w przyszłości. W takim przypadku metoda nie uruchomi nowej liczby całkowitej, ale da ci pamięć podręczną, dzięki czemu "tworzenie" nowej Integer będzie szybsze i łatwiejsze w zapamiętywaniu.

W ten sposób możesz spowodować wiele problemy, jeśli jesteś niedoświadczonym programistą java, ponieważ wywnioskowałeś, że Integer.valueOf(342)==Integer.valueOf(342), ponieważ możesz (lub nie) mieć ten sam wskaźnik dla dwóch liczb całkowitych, i prawdopodobnie będziesz ćwiczyć to w pewien sposób, powiedzmy, uczyłeś się w języku C#, aby będzie od czasu do czasu pokazywać błędy i nie będziesz wiedział, skąd pochodzą &, z których pochodzą ...

2

Z kodu źródłowego java.lang.Integer. Pamięć podręczna Integer jest konfigurowalna. Aby skonfigurować rozmiar pamięci podręcznej Integer inny niż Sun, musimy użyć właściwości System java.lang.Integer.IntegerCache.high zgodnie z kodem źródłowym.

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

Od java.lang.Short, java.lang.Byte i java.lang.Long tworzy pamięć podręczną 127 do -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)); 
    } 
}