Вопрос-ответ

Weird Integer boxing in Java

Странный целочисленный блок в Java

Я только что видел код, похожий на этот:

public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.out.println(a == b);

Integer c = 100, d = 100;
System.out.println(c == d);
}
}

При запуске этот блок кода будет распечатан:

false
true

Я понимаю, почему первый false: потому что два объекта являются отдельными объектами, поэтому == сравнивает ссылки. Но я не могу понять, почему второй оператор возвращает true? Существует ли какое-то странное правило автоматической блокировки, которое срабатывает, когда значение целого числа находится в определенном диапазоне? Что здесь происходит?

Переведено автоматически
Ответ 1

true Строка фактически гарантируется спецификацией языка. Из раздела 5.1.7:


Если значение p, которое помещается в блок, является true, false, байтом, символом в диапазоне от \ u0000 до \ u007f, или int или коротким числом от -128 до 127, то пусть r1 и r2 будут результатами любых двух конверсий p в блок. Всегда бывает, что r1 == r2.


Обсуждение продолжается, предполагая, что, хотя ваша вторая строка вывода гарантирована, первая - нет (см. Последний абзац, цитируемый ниже):


В идеале упаковка заданного примитивного значения p всегда давала бы идентичную ссылку. На практике это может быть невозможно при использовании существующих методов реализации. Приведенные выше правила являются прагматичным компромиссом. Последнее предложение выше требует, чтобы определенные общие значения всегда помещались в неотличимые объекты. Реализация может кэшировать их, лениво или нетерпеливо.


Для других значений эта формулировка запрещает любые предположения программиста об идентичности упакованных значений. Это позволило бы (но не требовало) совместного использования некоторых или всех этих ссылок.


Это гарантирует, что в большинстве распространенных случаев поведение будет желаемым без чрезмерного снижения производительности, особенно на небольших устройствах. Реализации с меньшим объемом памяти могут, например, кэшировать все символы и короткие значения, а также целые и длинные значения в диапазоне -32K - + 32K.


Ответ 2
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000; //1
System.out.println(a == b);

Integer c = 100, d = 100; //2
System.out.println(c == d);
}
}

Вывод:

false
true

Да, первый вывод создается для сравнения ссылки; 'a' и 'b' - это две разные ссылки. В пункте 1 фактически создаются две ссылки, которые похожи на -

Integer a = new Integer(1000);
Integer b = new Integer(1000);

Второй вывод создается потому, что JVM пытается сэкономить память, когда Integer попадает в диапазон (от -128 до 127). В точке 2 для 'd' не создается новая ссылка типа Integer . Вместо создания нового объекта для ссылочной переменной целочисленного типа 'd', он присваивается только ранее созданному объекту, на который ссылается 'c'. Все это выполняется JVM.

Эти правила экономии памяти предназначены не только для целых чисел. в целях экономии памяти два экземпляра следующих объектов-оболочек (при создании с помощью упаковки) всегда будут ==, где их примитивные значения одинаковы -


  • Логическое значение

  • Байт

  • Символ от \u0000 до \u007f (7f равно 127 в десятичной системе счисления)

  • Короткое и целое число от -128 до 127

Ответ 3

Целочисленный кэш - это функция, которая была введена в Java версии 5 в основном для :


  1. Экономия места в памяти

  2. Повышение производительности.

Integer number1 = 127;
Integer number2 = 127;

System.out.println("number1 == number2" + (number1 == number2);

ВЫВОД: True


Integer number1 = 128;
Integer number2 = 128;

System.out.println("number1 == number2" + (number1 == number2);

ВЫВОД: False

КАК?

На самом деле, когда мы присваиваем значение целочисленному объекту, он делает автоматическое продвижение незаметно.

Integer object = 100;

на самом деле вызывается функция Integer.valueOf()

Integer object = Integer.valueOf(100);

Подробные сведения о valueOf(int)

    public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

Описание:


Этот метод всегда будет кэшировать значения в диапазоне от -128 до 127 включительно и может кэшировать другие значения за пределами этого диапазона.


Когда требуется значение в диапазоне от -128 до 127, оно каждый раз возвращает постоянную ячейку памяти. Однако, когда нам нужно значение больше 127

return new Integer(i);

возвращает новую ссылку каждый раз, когда мы инициируем объект.


Кроме того, == operators в Java используются для сравнения двух ссылок на память, а не значений.

Object1 находится, скажем, на отметке 1000 и содержит значение 6.

Object2 находится, скажем, по адресу 1020 и содержит значение 6.

Object1 == Object2 это False поскольку они имеют разные ячейки памяти, хотя и содержат одинаковые значения.

Ответ 4

Целочисленные объекты в некотором диапазоне (я думаю, возможно, от -128 до 127) кэшируются и используются повторно. Целые числа за пределами этого диапазона каждый раз получают новый объект.

2023-12-10 10:28 java