В интервью одного из моих друзей спросили, что если у нас есть два целочисленных объекта, Целое число; Целое число;
Почему a
оценивается как истина
, когда оба содержат два отдельных объекта? В этой статье я попытаюсь ответить на этот вопрос, а также попытаюсь объяснить ответ.
Короткий Ответ
Краткий ответ на этот вопрос таков: прямое присвоение литерала int
ссылке Целое число
является примером концепции автоматического бокса, в которой код преобразования литерального значения в объект обрабатывается компилятором, поэтому на этапе компиляции компилятор преобразует Целое число;
в Целое.valueOf(127);
.
Класс Integer
поддерживает внутренний кэш целых чисел для целых чисел, который по умолчанию находится в диапазоне от -128 до 127
и Метод Integer.valueOf()
возвращает объекты указанного диапазона из этого кэша. Итак, a
возвращает true, потому что a
и b
оба указывают на один и тот же объект.
Длинный Ответ
Чтобы понять краткий ответ, давайте сначала разберемся в типах Java, все типы в Java подразделяются на две категории
Примитивные типы: В Java существует 8 примитивных типов (byte, short, int, long, float, double, char и boolean), которые хранят свои значения непосредственно в виде двоичных битов. Например,
int; int;
здесьa
иb
непосредственно содержит двоичное значение 5, и если мы попытаемся сравнитьa
иb
используяa
мы на самом деле сравниваем5
который возвращает true.Типы ссылок: Все типы, отличные от примитивных типов, относятся к категории ссылочных типов, например, Классы, интерфейсы, Перечисления, массивы и т.д., А ссылочные типы содержат адрес объекта вместо самого объекта. Например,
Целое целое(5); Целое целое(5)
, здесь a и b не содержат двоичного значения5
вместоa
иb
содержит адреса памяти двух отдельных объектов, где оба объекта содержат значение5
. Поэтому, если мы попытаемся сравнитьa
иb
используяa,
мы фактически сравниваем эти два отдельных адреса памяти, поэтому получаемfalse
, чтобы выполнить фактическое равенство дляa
иb
нам нужно выполнитьa.равно(b)
.Типы ссылок далее делятся на 4 категории Сильные, Мягкие, Слабые и Фантомные ссылки .
И мы знаем, что Java предоставляет классы-оболочки для всех примитивных типов и поддерживает автоматическую упаковку и автоматическую распаковку.
// Example of auto-boxing, here c is a reference type Integer c = 128; // Compiler converts this line to Integer c = Integer.valueOf(128); // Example of auto-unboxing, here e is a primitive type int e = c; // Compiler converts this line to int e = c.intValue();
Теперь, если мы создадим два целочисленных объекта a
и b,
и попробуйте сравнить их с помощью оператора равенства ==
, мы получим false
, потому что обе ссылки содержат разные-разные объекты
Integer a = 128; // Compiler converts this line to Integer a = Integer.valueOf(128); Integer b = 128; // Compiler converts this line to Integer b = Integer.valueOf(128); System.out.println(a == b); // Output -- false
Но если мы присвоим значение 127
для обоих a
и b
и попробуйте сравнить их с помощью оператора равенства ==
, мы получим истину
почему?
Integer a = 127; // Compiler converts this line to Integer a = Integer.valueOf(127); Integer b = 127; // Compiler converts this line to Integer b = Integer.valueOf(127); System.out.println(a == b); // Output -- true
Как мы видим в коде, мы назначаем разные объекты a
и b
но a
может возвращать значение true только в том случае, если оба a
и b
указывают на один и тот же объект.
Так как же сравнение возвращается верным? что здесь на самом деле происходит? являются a
и b
указывающий на один и тот же объект?
Ну, до сих пор мы знаем, что код Integer;
является примером автобоксинга, и компилятор автоматически преобразует эту строку в Integer.valueOf(127);
.
Таким образом, это метод Integer.valueOf()
, который возвращает эти целочисленные объекты, что означает, что этот метод должен что-то делать под капотом.
И если мы взглянем на исходный код метода Integer.valueOf()
, мы ясно увидим, что если переданный литерал int i
больше, чем Целочисленный кэш.низкий
и менее Целочисленный кэш.высокий
затем метод возвращает целочисленные объекты из Целочисленного кэша
. Значения по умолчанию для IntegerCache.низкий
и Целочисленный кэш.высокие
являются -128
и 127
соответственно.
Другими словами, вместо создания и возврата новых целочисленных объектов метод Integer.valueOf()
возвращает целочисленные объекты из внутреннего Кэш целых чисел
если переданный литерал int больше -128
и менее 127
.
/** * Returns an {@code Integer} instance representing the specified * {@code int} value. If a new {@code Integer} instance is not * required, this method should generally be used in preference to * the constructor {@link #Integer(int)}, as this method is likely * to yield significantly better space and time performance by * caching frequently requested values. * * This method will always cache values in the range -128 to 127, * inclusive, and may cache other values outside of this range. * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
Java кэширует целочисленные объекты, которые попадают в диапазон от -128 до 127, потому что этот диапазон целых чисел часто используется в повседневном программировании, что косвенно экономит некоторую память.
Как вы можете видеть на следующем изображении Целое число
класс поддерживает внутреннюю статическую IntegerCache
класс, который действует как кэш и содержит целочисленные объекты от -128 до 127, и поэтому, когда мы пытаемся получить целочисленный объект для 127
мы всегда получаем один и тот же объект.
Кэш инициализируется при первом использовании, когда класс загружается в память из-за статического блока . Максимальный диапазон кэша можно регулировать с помощью параметра
-XX:AutoBoxCacheMax
JVM.
Такое поведение кэширования неприменимо к Целому числу
только объекты, похожие на Целое число.
только объекты, похожие на Целое число.
, ,
Короткий кэш
, Кэш журналов
, Кэш символов
для Байта
, Короткий
, Длинный
,
Байт, короткий и длинный имеют фиксированный диапазон для кэширования от -127 до 127 (включительно), но для символов диапазон составляет от 0 до 127 (включительно). Диапазон может быть изменен с помощью аргумента только для целого числа, но не для других.
Вы можете найти полный исходный код этой статьи в этом репозитории Github и, пожалуйста, не стесняйтесь оставлять свои ценные отзывы.
Оригинал: “https://dev.to/njnareshjoshi/java-integer-cache-why-integer-valueof-127-integer-valueof-127-is-true-643”