Рубрики
Без рубрики

Кэш Целых Чисел Java: Почему Integer.valueOf(127).значение(127) Является Истинным

В интервью одного из моих друзей спросили, что если у нас есть два целочисленных объекта, Целое число; В … Помеченный java.

В интервью одного из моих друзей спросили, что если у нас есть два целочисленных объекта, Целое число; Целое число; Почему a оценивается как истина , когда оба содержат два отдельных объекта? В этой статье я попытаюсь ответить на этот вопрос, а также попытаюсь объяснить ответ.

Короткий Ответ

Краткий ответ на этот вопрос таков: прямое присвоение литерала int ссылке Целое число является примером концепции автоматического бокса, в которой код преобразования литерального значения в объект обрабатывается компилятором, поэтому на этапе компиляции компилятор преобразует Целое число; в Целое.valueOf(127); .

Класс Integer поддерживает внутренний кэш целых чисел для целых чисел, который по умолчанию находится в диапазоне от -128 до 127 и Метод Integer.valueOf() возвращает объекты указанного диапазона из этого кэша. Итак, a возвращает true, потому что a и b оба указывают на один и тот же объект.

Длинный Ответ

Чтобы понять краткий ответ, давайте сначала разберемся в типах Java, все типы в Java подразделяются на две категории

  1. Примитивные типы: В Java существует 8 примитивных типов (byte, short, int, long, float, double, char и boolean), которые хранят свои значения непосредственно в виде двоичных битов. Например, int; int; здесь a и b непосредственно содержит двоичное значение 5, и если мы попытаемся сравнить a и b используя a мы на самом деле сравниваем 5 который возвращает true.

  2. Типы ссылок: Все типы, отличные от примитивных типов, относятся к категории ссылочных типов, например, Классы, интерфейсы, Перечисления, массивы и т.д., А ссылочные типы содержат адрес объекта вместо самого объекта. Например, Целое целое(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”