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), но до сих пор никто не сообщал о проблеме после нескольких сотен тестов, выполняющих этот фрагмент кода.

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

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

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

Ответ 2

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

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

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


Ресурсы:

В той же теме:

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

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