Jeśli chodzi o moje poprzednie pytanie, dlaczego == porównania z Integer.valueOf (String) dają różne wyniki dla 127 i 128? , wiemy, że Integer
class
ma pamięć podręczną, która przechowuje wartości między -128
a 127
.
Zastanawiam się tylko, dlaczego między -128 a 127 ?
Dokumentacja Integer.valueOf () stwierdza, że " buforuje często żądane wartości " . Ale czy wartości pomiędzy -128
i 127
są często wymagane naprawdę? Myślałem, że często wymagane wartości są bardzo subiektywne.
Czy jest jakikolwiek możliwy powód?
W dokumentacji stwierdzono również: „... i może buforować inne wartości spoza tego zakresu. ”
Jak można to osiągnąć?
Odpowiedzi:
Zastanawiam się tylko, dlaczego między -128 a 127?
W pamięci podręcznej może być przechowywany większy zakres liczb całkowitych , ale przynajmniej te między -128 a 127 muszą być buforowane, ponieważ jest to wymagane przez specyfikację języka Java (wyróżnienie moje):
Uzasadnienie tego wymogu wyjaśniono w tym samym akapicie:
Jak mogę buforować inne wartości spoza tego zakresu.?
Możesz użyć
-XX:AutoBoxCacheMax
opcji JVM, która nie jest tak naprawdę udokumentowana na liście dostępnych opcji JVM Hotspot . Jest to jednak wspomniane w komentarzach wewnątrzInteger
klasy wokół wiersza 590 :Należy pamiętać, że jest to specyficzne dla implementacji i może, ale nie musi być dostępne w innych maszynach JVM.
źródło
-128 do 127 to rozmiar domyślny. Ale javadoc mówi również, że rozmiar pamięci podręcznej Integer może być kontrolowany przez
-XX:AutoBoxCacheMax=<size>
opcję. Zauważ, że ustawia tylko wysoką wartość, niska wartość to zawsze -128. Ta funkcja została wprowadzona w wersji 1.6.Co do tego, dlaczego od -128 do 127 - jest to zakres wartości bajtów i naturalne jest użycie go dla bardzo małej pamięci podręcznej.
źródło
-XX:AutoBoxCacheMax=<size>
?java -XX:AutoBoxCacheMax=256
w konsoli, otrzymałemError:could not create the Java Virtual Machine
Powodem buforowania małych liczb całkowitych, jeśli o to pytasz, jest to, że wiele algorytmów używa małych liczb całkowitych w swoich obliczeniach, więc unikanie narzutu tworzenia obiektów dla tych wartości wydaje się być opłacalne.
Powstaje wtedy pytanie, które liczby całkowite mają być buforowane. Ponownie, mówiąc ogólnie, częstotliwość, z jaką używane są wartości stałe, ma tendencję do zmniejszania się wraz ze wzrostem wartości bezwzględnej stałej - wszyscy spędzają dużo czasu na wartościach 1, 2 lub 10, stosunkowo niewielu bardzo używa wartości 109 intensywnie; mniej będzie miało wydajność zależną od tego, jak szybko można uzyskać liczbę całkowitą dla 722. Java zdecydowała się przydzielić 256 przedziałów obejmujących zakres wartości bajtu ze znakiem. Decyzja ta mogła zostać oparta na analizie programów istniejących w tamtym czasie, ale równie prawdopodobne jest, że była to decyzja czysto arbitralna. Jest to rozsądna ilość miejsca do zainwestowania, można uzyskać do niej szybki dostęp (maska, aby dowiedzieć się, czy wartość mieści się w zakresie pamięci podręcznej, a następnie szybkie wyszukiwanie w tabeli, aby uzyskać dostęp do pamięci podręcznej) i na pewno obejmie najczęstsze przypadki.
Innymi słowy, myślę, że odpowiedź na twoje pytanie brzmi: „nie jest tak subiektywne, jak myślałeś, ale dokładne granice są w dużej mierze decyzją opartą na regułach ... a eksperymentalne dowody wskazują, że było wystarczająco dobre. "
źródło
Maksymalną wartość całkowitą, która może być buforowana, można skonfigurować za pomocą właściwości systemowej, tj.
java.lang.Integer.IntegerCache.high
(-XX:AutoBoxCacheMax
). Pamięć podręczna jest implementowana przy użyciu tablicy.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() {} }
źródło
Kiedy napotkasz klasę Integer i zawsze masz ramkę w zakresie od -128 do 127, zawsze lepiej jest przekonwertować obiekt Integer na wartość int, jak poniżej.
źródło