Я использовал Sonar, чтобы сделать мой код более чистым, и он указал, что я использую new Integer(1)
вместо Integer.valueOf(1)
. Потому что кажется, что valueOf
не создает экземпляр нового объекта, поэтому он более удобен для памяти. Как valueOf
не создавать экземпляр нового объекта? Как это работает? Это верно для всех целых чисел?
Новый Integer vs valueOf
Ответ 1
Integer.valueOf реализует кеш для значений от -128 до +127. См. Последний параграф Спецификации языка Java, раздел 5.1.7, в котором объясняются требования к боксу (обычно реализуются в терминах методов .valueOf).
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7
Ответ 2
Из JavaDoc:
public static Integer valueOf (int i) Возвращает экземпляр Integer, представляющий указанное значение int. Если новый экземпляр Integer не требуется, этот метод обычно должен использоваться в предпочтении конструктору Integer (int), так как этот метод может обеспечить значительно лучшую производительность пространства и времени, кэшируя часто запрашиваемые значения.
ValueOf
широко используется для автобоксинга и поэтому (при использовании для автобоксинга) кэширует по меньшей мере значения от -128 до 127, чтобы следовать спецификации автобоксинга.
Вот реализация ValueOf
для Sun JVM 1.5.? Посмотрите на весь класс, чтобы узнать, как инициализируется кеш.
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);
}
Ответ 3
они подталкивают вас использовать valueOf()
вместо new Integer()
, поэтому метод valueOf()
делает это для вас и кэширует значение, если вы захотите снова получить тот же номер в будущем. В этом случае метод не будет устанавливать новый Integer, но даст вам кешированный, что сделает "создание" нового Integer намного более быстрым и удобным для памяти процессом.
Таким образом, вы можете столкнуться с множеством проблем, если вы являетесь неисследованным Java-программистом, так как вы сделаете вывод, что Integer.valueOf(342)==Integer.valueOf(342)
, потому что вы можете (или не можете) иметь один и тот же указатель для двух целых чисел, и, вероятно, вы будете практиковать его в способ, скажем, вы узнали на С#, чтобы время от времени показывали вам ошибки, и вы не знаете, как и откуда они пришли...
Ответ 4
Из исходного кода java.lang.Integer. Integer кеш настраивается. Чтобы настроить размер кеша Integer, отличный от Sun, нам нужно использовать свойство System java.lang.Integer.IntegerCache.high
в соответствии с исходным кодом.
/**
* 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 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() {}
}
Из java.lang.Short, java.lang.Byte и java.lang.Long создает кеш размером от 127 до -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));
}
}