Почему равный оператор работает для значения Integer до 128 числа?

Почему Integer «=» оператор не работает для 128 и после значений Integer? Может ли кто-нибудь объяснить эту ситуацию?

Это моя среда Java: версия java «1.6.0_37»

Java (TM) SE Runtime Environment (assembly 1.6.0_37-b06)

Java HotSpot (TM) 64-разрядная серверная VM (assembly 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 

Благодаря!

Проверьте исходный код Integer . Вы можете увидеть кеширование значений там.

Кэширование происходит, только если вы используете Integer.valueOf(int) , а не если используете new Integer(int) . Используемый вами Integer.valueOf использует Integer.valueOf

Согласно JLS , вы всегда можете рассчитывать на то, что для значений от -128 до 127 вы получаете идентичные объекты Integer после автобоксинга, а на некоторых реализациях вы можете получить одинаковые объекты даже для более высоких значений.

Фактически в Java 7 (и я думаю, что в новых версиях Java 6) реализация classа IntegerCache изменилась, а верхняя граница больше не жестко запрограммирована, но настраивается через свойство «java.lang.Integer.IntegerCache. high “, поэтому, если вы запустите свою программу с параметром VM -Djava.lang.Integer.IntegerCache.high=1000 , вы получите« одинаковые значения »для всех значений.

Но JLS все еще гарантирует это только до 127:

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

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

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

Integer – это class оболочки для int .

Integer != Integer сравнивает фактическую ссылку на объект, где int != int будет сравнивать значения.

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

Если вне этого диапазона, будут созданы отдельные объекты, поэтому ссылка будет отличаться.

Исправить это:

  • Сделайте типы int или
  • Передать типы в int или
  • Использовать .equals()

Согласно спецификациям Java Language:

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

JLS Boxing Conversions

Обратитесь к этой статье за ​​дополнительной информацией о кэшировании int

Объект 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's 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 для сравнения значений.

Используйте .equals() вместо == .

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

 if (a.equals(b)) { ... } 

В зависимости от того, как вы получаете экземпляры Integer , он может не работать для какого-либо значения:

 System.out.println(new Integer(1) == new Integer(1)); 

печать

 false 

Это связано с тем, что оператор == применяемый к операндам с типизированным типом, не имеет ничего общего со значением, которое представляют эти операнды.

Это потому, что логика реализации classа Integer . Он подготовил объекты для чисел до 128. Вы можете проверить http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Integer.java источник открытого -jdk, например (поиск кеша []).
В принципе, объекты не следует сравнивать с помощью == вообще, за одним исключением из Enums.

  • «Недопустимый файл подписи» при попытке запустить .jar
  • Есть ли библиотека Java, которая может «отличать» два объекта?
  • Процесс автоматического перезапуска при сбое
  • Как узнать, был ли запрос на сервлет выполнен с использованием HTTP или HTTPS?
  • Программно импортировать сертификат доверия CA в существующий файл хранилища ключей без использования keytool
  • Исключение с использованием HttpRequest.execute (): недопустимое использование SingleClientConnManager: соединение все еще выделено
  • Java обращает значение int без использования массива
  • Что заставляет JNI звонить медленно?
  • Реализация протокола X-modem в Java
  • Любые простые (и современные) Java-фреймворки для встраивания фильмов в приложение Swing?
  • doGet и doPost в сервлетах
  • Давайте будем гением компьютера.