Java: целое число равно против == - PullRequest
137 голосов
/ 03 сентября 2010

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

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

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

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

Ответы [ 5 ]

215 голосов
/ 03 сентября 2010

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

70 голосов
/ 03 сентября 2010

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

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

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


Ресурсы:

На ту же тему:

5 голосов
/ 03 сентября 2010

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

4 голосов
/ 03 сентября 2010

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

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

mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );
3 голосов
/ 28 июля 2016

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

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

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

...