2010-09-03 5 views
106

С точки зрения Java 1.5 вы можете в значительной степени обменивать Integer с int во многих ситуациях.Java: Целое число равно ==

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

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

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 содержит довольно немного дополнительной информации. Это на самом деле был бы ответил на мой оригинальный вопрос, а потому, что я не упомянул Autoboxing в моем вопросе, он не появлялся в выбранных предложений:

Why can't the compiler/JVM just make autoboxing “just work”?

ответ

177

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

+1

Спасибо, это точно объясняет, почему 137 терпит неудачу! И он также отвечает на мой вопрос о том, почему это не распространенная проблема, в 95% случаев, с которыми я столкнулся, значение будет ниже 127. Хорошо поймать это сейчас, хотя для 5%, где это не так. –

+0

Интересная заметка: до пары недель назад cdiCt и cdsCt были как ints, так что все было в порядке, но мне пришлось сделать их целыми, чтобы проверить нулевую ситуацию, которая обрабатывается по-разному ... –

+2

@Jeremy Да, это довольно неясная проблема, но в качестве общего правила вы используете .equals() для объектов и == для примитивов. Вы не можете полагаться на autounboxing для тестирования равенства. – Adam

5

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

+0

Хороший ответ, но это не объясняет, почему он только не за 137 –

+0

Doh, я пропустил эту часть. – MattC

4

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

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

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

Хорошо, но я не делаю то, что делаю. Это было упрощено. –

+0

Вот как должен быть написан код, и это должен быть принятый ответ. ** Всегда ** сравнивать объекты с .equals(). Зачем использовать кешированные целые числа и оставить свой код на случай? – NobleUplift

61

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

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

Если значение р будучи в штучной упаковке является истинным, ложным, байты, полукокс в диапазоне \ u0000 к \ u007f, или INT или короткое число в диапазоне от -128 до 127, то пусть r1 и r2 быть результаты любых двух бокс-конверсий на стр. Всегда бывает, что r1 == r2.


Ресурсы:

На эту же тему:

+0

Спасибо, я отметил первый ответ как правильный. –

+0

О, я думаю, я могу отметить их как правых. Отметьте для вас тоже. –

+0

@Jeremy, на самом деле вы можете только отметить один как правый. Повторное нажатие на флажок изменяет принятый ответ. Не быть мелким; Ответ Колина превосходный. :) – Adam

1

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

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

Направить link для некоторой дополнительной информации