Что именно сравнивает Integer with == do?
ИЗМЕНИТЬ: ОК, ОК, я неправильно понял. Я не сравниваю int с Integer. Должен заметить.
В моей книге SCJP говорится:
Когда == используется для сравнения примитива к обертке, оболочка будет развернуты, и сравнение будет примитив к примитивному.
Итак, вы думаете, что этот код напечатает true
:
Integer i1 = 1; //if this were int it'd be correct and behave as the book says.
Integer i2 = new Integer(1);
System.out.println(i1 == i2);
но он печатает false
.
Кроме того, согласно моей книге, это должно печатать true
:
Integer i1 = 1000; //it does print `true` with i1 = 1000, but not i1 = 1, and one of the answers explained why.
Integer i2 = 1000;
System.out.println(i1 != i2);
Неа. Это false
.
Что дает?
Ответы
Ответ 1
Integer i1 = 1;
Integer i2 = new Integer(1);
System.out.println(i1 == i2);
Когда вы назначаете 1 в i1
, это значение помещается в бокс, создавая объект Integer
. Затем сравнение сравнивает две ссылки на объекты. Ссылки неравны, поэтому сравнение не выполняется.
Integer i1 = 100;
Integer i2 = 100;
System.out.println(i1 != i2);
Поскольку они инициализируются константами времени компиляции, компилятор может и делает их стажером и делает оба объекта одинаковыми с объектом Integer
.
(Обратите внимание, что я изменил значения от 1000 до 100. Как указывает @NullUserException, только маленькие целые числа интернированы.)
Вот действительно интересный тест. Посмотрите, можете ли вы это понять. Почему первая программа печатает true
, а вторая - false
? Используя свои знания по боксу и анализу времени компилятора, вы должны понять это:
// Prints "true".
int i1 = 1;
Integer i2 = new Integer(i1);
System.out.println(i1 == i2);
// Prints "false".
int i1 = 0;
Integer i2 = new Integer(i1);
i1 += 1;
System.out.println(i1 == i2);
Если вы это понимаете, попробуйте предсказать, что печатает эта программа:
int i1 = 0;
i1 += 1;
Integer i2 = new Integer(i1);
System.out.println(i1 == i2);
(После того, как вы догадались, запустите его и посмотрите!)
Ответ 2
Обратите внимание также, что более новые версии кэша Java Integer
в диапазоне от -128 до 127 (256 значений), что означает:
Integer i1, i2;
i1 = 127;
i2 = 127;
System.out.println(i1 == i2);
i1 = 128;
i2 = 128;
System.out.println(i1 == i2);
Будет напечатан true
и false
. (см. раздел ideone)
Мораль: Чтобы избежать проблем, всегда используйте .equals()
при сравнении двух объектов.
Вы можете полагаться на unboxing, когда вы используете ==
для сравнения обернутого примитива с примитивом (например: Integer
с int
), но если вы сравниваете два Integer
с ==
, которые будут не удалось объяснить причины @dan04.
Ответ 3
Вы не сравниваете примитив с оберткой. Вы сравниваете две обертки (ссылочные типы). ==
сравнивает идентификатор объекта, который возвращает false
, потому что это разные объекты.
Ответ 4
Нет, я бы не подумал, что этот код напечатал true, и вы сами ответили, почему именно.
Когда == используется для сравнения примитива к обертке, оболочка будет развернуты, и сравнение будет примитив к примитивному.
после чего вы сравнили две ссылки Integer, то есть сравнили адрес памяти i1 и i2. Вы хотели либо
Integer i1 = 1;
Integer i2 = new Integer(1);
System.out.println(i1.equals(i2));
Или
int i1 = 1;
Integer i2 = new Integer(1);
System.out.println(i1 == i2);
Ответ 5
Обратите внимание, что вы неправильно читаете выдержку, которую вы цитировали. Выдержка специально ограничивает его выражение для таких сравнений:
int k = 1;
Integer l = new Integer(1);
System.out.println(l == k);
Ответ 6
Начиная с Java 5.0, есть автоматический бокс и unboxing, что означает, что обертки могут быть неявно преобразованы в примитивы и наоборот. Однако, если вы сравниваете два объекта Integer, вы по-прежнему сравниваете две ссылки, и нет ничего, что могло бы привести к автоматическому боксу/распаковке. Если бы это было так, код, написанный на J2SE 1.4 и предыдущем, сломался.
Ответ 7
Предположим, что пусть имеет пример
Каков будет выход этого программного кода?
public class autoboxing {
public static void main(String a args) {
Integer a = new Integer(127);
Integer b = new Integer(127);
Integer c = 127;
Integer d = 127;
Integer e = new Integer(200);
Integer f = new Integer(200);
Integer g = 200;
Integer h = 200;
System.out.println((a == b) + ' " + (c =-- d) + " " + (e==f)+ " "+ (g == h));
.
Когда вы создаете объект Integer с новым оператором, он каждый раз возвращает новый объект. Когда вы сравниваете две контрольные переменные с оператором "==" , если две ссылочные переменные относятся к двум различным объектам, оператор "==" возвращает false.
Итак,
(a == b) и (e == f) выражения возвращают false. Integer класс кэширует значения от -128 до 127.
Когда вы сравниваете два объекта Integer с оператором "==" , если эти два целочисленных объекта создаются с помощью autoboxing, тогда вызывается метод value0f (int i).
ОТВЕТ: False True False False
Ниже приведена реализация этого метода
public static Integer value0f(int i) {
if (i >= IntegerCachedow && i <= IntegerCache.high)
return IntegerCache.cacheli + (-IntegerCachedow));
return new Integer(i);
Из приведенной выше реализации ниже приведены выводы
-
Если два значения объектов Integer находятся между -128 и 127, этот метод возвращает одинаковые значения.
Итак (c == d) возвращает true.
-
Если два значения объектов Integer находятся за пределами диапазона от -128 до 127, этот метод возвращает разные новые объекты Integer. Итак, (g ==
h) возвращает false
Подробнее о методе здесь:
https://stackoverflow.com/info/20897020/why-integer-class-caching-values-in-the-range-128-to-127