Почему равный оператор работает для значения Integer до 128 числа?
Почему Integer "=" оператор не работает для 128 и после значений Integer? Может ли кто-нибудь объяснить эту ситуацию?
Это моя среда Java:
java version "1.6.0_37"
Java (TM) SE Runtime Environment (сборка 1.6.0_37-b06)
Java HotSpot (TM) 64-разрядная серверная VM (сборка 20.12-b01, смешанный режим)
Пример кода:
Integer a;
Integer b;
a = 129;
b = 129;
for (int i = 0; i < 200; i++) {
a = i;
b = i;
if (a != b) {
System.out.println("Value:"+ i + " - Different values");
} else {
System.out.println("Value"+ i + " Same values");
}
}
Некоторая часть вывода консоли:
Value:124 - Same values
Value:125 - Same values
Value:126 - Same values
Value:127 - Same values
Value:128 - Different values
Value:129 - Different values
Value:130 - Different values
Value:131 - Different values
Value:132 - Different values
Спасибо!
Ответы
Ответ 1
Проверьте исходный код Integer. Вы можете увидеть кеширование значений там.
Кэширование происходит только в том случае, если вы используете Integer.valueOf(int)
, а не при использовании new Integer(int)
. Используемый вами автобоксинг использует Integer.valueOf
В соответствии с JLS вы всегда можете рассчитывать на то, что для значений от -128 до 127 вы получаете идентичные объекты Integer после autoboxing и на некоторых реализациях вы можете получить одинаковые объекты даже для более высоких значений.
Фактически в Java 7 (и я думаю, что в более новых версиях Java 6), реализация класса IntegerCache изменилась, а верхняя граница больше не жестко закодирована, но он настраивается через свойство "java.lang.Integer.IntegerCache.high", поэтому, если вы запустите свою программу с параметром VM -Djava.lang.Integer.IntegerCache.high=1000
, вы получите "Те же значения" для всех значений.
Но JLS все еще гарантирует это только до 127:
В идеале, бокс данного примитивного значения p всегда будет давать идентичную ссылку. На практике это может оказаться невозможным с использованием существующих методов внедрения. Правила выше - прагматичный компромисс. Последнее заключительное предложение требует, чтобы определенные общие значения всегда помещались в неразличимые объекты. Реализация может кэшировать эти, лениво или нетерпеливо.
Для других значений эта формулировка запрещает любые предположения о идентичности вложенных значений в части программиста. Это позволило бы (но не требовать) совместного использования некоторых или всех этих ссылок.
Это гарантирует, что в большинстве распространенных случаев поведение будет желательным, не налагая чрезмерного штрафа за производительность, особенно на небольшие устройства. Меньшие реализации, ограниченные памятью, могут, например, кэшировать все символы и шорты, а также целые и длинные строки в диапазоне от -32K до + 32K.
Ответ 2
В соответствии со спецификациями Java Language:
Если значение p в коробке равно true, false, байт, a char в диапазоне \ u0000 to\u007f, или int или short number между -128 и 127, затем пусть r1 и r2 - результаты любых двух бокс-преобразований p. это всегда случай, когда r1 == r2.
JLS Boxing Conversions
Обратитесь к этой статье за дополнительной информацией о int-кешировании
Ответ 3
Integer
- это класс-оболочка для int
.
Integer != Integer
сравнивает фактическую ссылку на объект, где int != int
будет сравнивать значения.
Как уже указывалось, значения -128 - 127 кэшируются, поэтому для них возвращаются те же объекты.
Если вне этого диапазона будут созданы отдельные объекты, поэтому ссылка будет отличаться.
Чтобы исправить это:
- Сделайте типы
int
или
- Перечислите типы
int
или
- Используйте
.equals()
Ответ 4
Объект Integer имеет внутренний механизм кэширования:
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() {}
}
Также см. метод valueOf:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
Вот почему вы должны использовать valueOf
вместо new Integer
. Autoboxing использует этот кеш.
Также см. этот пост: https://effective-java.com/2010/01/java-performance-tuning-with-maximizing-integer-valueofint/
Использование ==
не является хорошей идеей, используйте equals для сравнения значений.
Ответ 5
Используйте .equals()
вместо ==
.
Целочисленные значения кэшируются только для чисел от -127 до 128, потому что они используются чаще всего.
if (a.equals(b)) { ... }
Ответ 6
В зависимости от того, как вы получаете экземпляры Integer
, он может не работать для какого-либо значения:
System.out.println(new Integer(1) == new Integer(1));
печатает
false
Это связано с тем, что оператор ==
, применяемый к операндам с типизированным типом, не имеет ничего общего со значением, которое представляют эти операнды.
Ответ 7
Это потому, что логика реализации класса Integer
. Он подготовил объекты для чисел до 128. Вы можете проверить http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Integer.java источник open-jdk, например (поиск в кеше []). < бр /" > В принципе, объекты не следует сравнивать с помощью ==
вообще, за одним исключением из Enums.