Сравнение значений Integer в Java, странное поведение
Прогулка со мной..
Integer x = 23;
Integer y = 23;
if (x == y)
System.out.println("what else"); // All is well as expected
else
System.out.println("...");
Пока
Integer x = someObject.getIndex();
Integer y = someOtherObject.getSomeOtherIndex();
if (x == y)
System.out.println("what else");
else
System.out.println("..."); // Prints this
Хмм... Я пробовал лить в int
int x = someObject.getIndex();
int y = someOtherObject.getSomeOtherIndex()
if (x == y)
System.out.println("what else"); // works fine
else
System.out.println("...");
Являются ли они оба целыми?
System.out.println(x.getClass().getName()); // java.lang.Integer
System.out.println(y.getClass().getName()); // java.lang.Integer
System.out.println(someObject.getIndex()); // java.lang.Integer
System.out.println(someOtherObject.getSomeOtherIndex()); // java.lang.Integer
Что вы, ребята, думаете? Что бы это объясняло?
Ответы
Ответ 1
Вы сравниваете значения Integer
, которые являются ссылками. Вы придумываете эти ссылки через autoboxing. Для некоторых значений (гарантируется от -128 до 127) JRE поддерживает кеш объектов Integer
. Для более высоких значений это не так. Из раздел 5.1.7 JLS:
Если значение p в боксе равно true, false, байту или char в диапазоне от \u0000 до\u007f или int или коротком числе между -128 и 127 (включительно), тогда пусть r1 и r2 - результаты любых двух бокс-преобразований p. Всегда бывает, что r1 == r2.
В идеале, бокс данного примитивного значения p всегда будет давать идентичную ссылку. На практике это может оказаться невозможным с использованием существующих методов внедрения. Правила выше - прагматичный компромисс. Последнее заключительное предложение требует, чтобы определенные общие значения всегда помещались в неразличимые объекты. Реализация может кэшировать эти, лениво или нетерпеливо. Для других значений эта формулировка запрещает любые предположения о идентичности вложенных значений в части программиста. Это позволило бы (но не требовать) совместного использования некоторых или всех этих ссылок.
Это гарантирует, что в большинстве распространенных случаев поведение будет желательным, не налагая чрезмерного штрафа за производительность, особенно на небольшие устройства. Менее ограниченные памятью реализации могут, например, кэшировать все char и короткие значения, а также значения int и long в диапазоне от -32K до + 32K.
Мораль: не сравнивайте ссылки Integer
, когда вас интересуют базовые значения int
. Используйте .equals()
или сначала получите значения int
.
Ответ 2
Чтобы правильно сравнить целые числа, вам нужно использовать .equals()
или сравнить их примитивные значения, нажав на int
или называя intValue()
на них.
Использование ==
проверяет, являются ли два целых объекта одним и тем же объектом, но не содержат ли они одинаковое числовое значение.
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println(a.equals(b)); //true
System.out.println((int)a == (int)b); //true
System.out.println(a.intValue() == b.intValue()); //true
System.out.println(a == b); //false
Отредактировано, чтобы проиллюстрировать точку Джона из JLS об автобоксинге:
Integer a = 1;
Integer b = 1;
System.out.println(a.equals(b)); //true
System.out.println((int)a == (int)b); //true
System.out.println(a.intValue() == b.intValue()); //true
System.out.println(a == b); //true
против
Integer a = 128;
Integer b = 128;
System.out.println(a.equals(b)); //true
System.out.println((int)a == (int)b); //true
System.out.println(a.intValue() == b.intValue()); //true
System.out.println(a == b); //false
Ответ 3
Похоже, что что-то напугано с автоматическим боксом, когда вы используете ==
для двух целых чисел.
Я бы предположил, что он отлично работает при использовании Integer
, если вы используете метод equals()
? Это, по моему мнению, все равно.
Вы не используете java 1.4 или что-то не так ли?