Java: целое число равно vs. ==

Начиная с Java 1.5, вы можете в значительной степени обменивать Integer с int во многих ситуациях.

Тем не менее, я нашел потенциальный дефект в моем коде, который немного меня удивил.

Следующий код:

 Integer cdiCt = ...; Integer cdsCt = ...; ... if (cdiCt != null && cdsCt != null && cdiCt != cdsCt) mismatch = true; 

казалось, неправильно устанавливали несоответствие, когда значения были равны, хотя я не могу определить, при каких обстоятельствах. Я установил точку останова в Eclipse и увидел, что значения Integer равны 137, и я проверил логическое выражение, и он сказал, что это неверно, но когда я перешагнул его, он установил несоответствие true.

Изменение условного выражения:

 if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt)) 

исправлена ​​проблема.

Может ли кто-нибудь пролить свет на то, почему это произошло? До сих пор я видел поведение на своем локальном хосте на своем собственном компьютере. В этом конкретном случае код успешно завершил около 20 сравнений, но не смог выполнить 2. Проблема была последовательно воспроизводимой.

Если это распространенная проблема, она должна вызывать ошибки в наших других средах (dev и test), но до сих пор никто не сообщал об этой проблеме после нескольких сотен тестов, выполняющих этот fragment кода.

Нельзя ли использовать == для сравнения двух значений Integer ?

В дополнение ко всем тонким ответам ниже, следующая ссылка stackoverflow имеет довольно немного дополнительной информации. Фактически это ответило бы на мой первоначальный вопрос, но поскольку я не упоминал автобоксинг в своем вопросе, он не отображался в выбранных предложениях:

Почему компилятор / JVM просто не делает автобоксинг «просто работать»?

JVM кэширует значения Integer. == работает только для чисел от -128 до 127 http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

Вы не можете сравнить два Integer с простым == это объекты, поэтому большинство ссылок на время не будут одинаковыми.

Существует трюк с целым Integer.valueOf() от -128 до 127, ссылки будут такими же, как и autoboxing, использует Integer.valueOf() который кэширует маленькие целые числа.

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


Ресурсы :

  • JLS – Бокс

По той же теме:

  • автобоксинг против ручного бокса java

Проблема в том, что ваши два объекта Integer – это просто объекты. Они не совпадают, потому что вы сравниваете свои две ссылки на объекты, а не значения внутри. Очевидно, что .equals переопределяется, чтобы обеспечить сравнение значений, а не сравнение ссылок на объекты.

Integer относится к ссылке, то есть при сравнении ссылок, которые вы сравниваете, если они указывают на один и тот же объект, а не на значение. Следовательно, проблема, которую вы видите. Причина, по которой он работает с обычными типами int заключается в том, что он освобождает значение, содержащееся в Integer .

Могу ли я добавить, что если вы делаете то, что делаете, зачем начинать утверждение if ?

 mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) ); 

«==» всегда сравнивает расположение памяти или ссылки на объекты значений. метод equals всегда сравнивает значения. Но equals также косвенно использует оператор «==» для сравнения значений.

Integer использует Integer cache для хранения значений от -128 до +127. Если оператор == используется для проверки любых значений от -128 до 127, тогда он возвращает true. иначе, чем эти значения, он возвращает false.

См. Ссылку для дополнительной информации.

Давайте будем гением компьютера.