Что именно делает сравнение целых чисел с ==?
РЕДАКТИРОВАТЬ: ОК, хорошо, я неправильно прочитал. Я не сравниваю int с целым числом. Верно подмечено.
Моя книга 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
,
Что дает?
7 ответов
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);
(После того, как вы угадаете, запустите его и посмотрите!)
Также обратите внимание, что более новые версии кеша Java Integer
s в диапазоне от -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()
при сравнении двух объектов.
Вы можете положиться на распаковку при использовании ==
сравнить упакованный примитив с примитивом (например: Integer
с int
), но если вы сравниваете два Integer
с ==
это не удастся по причинам, объясненным @dan04.
Вы не сравниваете примитив с оберткой. Вы сравниваете две обертки (ссылочные типы). ==
сравнивает идентификатор объекта, который возвращает false
потому что они разные объекты.
Обратите внимание, что вы неправильно прочитали цитату, которую вы цитировали. Отрывок специально ограничивает это утверждение сравнениями, подобными этим:
int k = 1;
Integer l = new Integer(1);
System.out.println(l == k);
Нет, я бы не подумал, что этот код напечатан верно, и вы сами ответили, почему.
Когда == используется для сравнения примитива с оберткой, обертка будет развернута и сравнение будет примитивом примитива.
Затем вы сравнили две целочисленные ссылки, то есть сравнили адреса памяти 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);
Начиная с Java 5.0, есть автоматическая упаковка и распаковка, что означает, что обертки могут быть неявно преобразованы в примитивы и наоборот. Однако, если вы сравниваете два объекта Integer, вы все равно сравниваете две ссылки, и нет ничего, что могло бы вызвать автоматическую упаковку / распаковку. Если бы это было так, код, написанный на J2SE 1.4 и более ранних версиях, сломался бы.
Пусть пусть есть пример
Каким будет вывод этого программного кода?
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. Целочисленный класс кэширует значения в диапазоне от -128 до 127.
Когда вы сравниваете два целочисленных объекта с оператором "==", если эти два целочисленных объекта создаются с помощью автобокса, будет вызван метод value0f (int i).
ОТВЕТ: Ложь Правда Ложь Ложь
Ниже приведена реализация этого метода
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://stackru.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127