Что именно делает сравнение целых чисел с ==? - PullRequest
11 голосов
/ 11 сентября 2010

РЕДАКТИРОВАТЬ: ОК, хорошо, я неправильно прочитал.Я не сравниваю 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 ]

12 голосов
/ 11 сентября 2010

Также обратите внимание, что более новые версии 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.

8 голосов
/ 11 сентября 2010
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);

(После того, как вы угадаете, запустите его и посмотрите! )

6 голосов
/ 11 сентября 2010

Вы не сравниваете примитив с оберткой. Вы сравниваете две обертки (ссылочные типы). == сравнивает идентификатор объекта, который возвращает false, потому что это разные объекты.

1 голос
/ 11 сентября 2010

Обратите внимание, что вы неправильно прочитали цитату, которую цитировали. Отрывок специально ограничивает это утверждение сравнениями, подобными этим:

int k = 1;
Integer l = new Integer(1);
System.out.println(l == k);
1 голос
/ 11 сентября 2010

Нет, я не думаю, что этот код печатается как true, и вы сами ответили, почему именно.

Когда == используется для сравнения примитива с оберткой, обертка будет развернута, иСравнение будет примитивным к примитивному.

, и вы затем сравнили две целочисленные ссылки, то есть сравнили адрес памяти 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);
0 голосов
/ 27 августа 2017

Предположим, у let есть пример

Каким будет вывод этого программного кода?

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);

Из приведенной выше реализации, ниже приведены выводы

  1. Если значения двух объектов типа Integer находятся в диапазоне от -128 до 127, этот метод возвращает одинаковые значения. Итак, (c == d) возвращает true.

  2. Если два значения объектов Integer находятся вне диапазона от -128 до 127, этот метод возвращает различные новые объекты Integer. Итак, (г == h) возвращает false

Подробнее о методе здесь: 1036 **

0 голосов
/ 11 сентября 2010

Начиная с Java 5.0, есть автоматическая упаковка и распаковка, что означает, что оболочки могут быть неявно преобразованы в примитивы и наоборот.Однако, если вы сравниваете два объекта Integer, вы все равно сравниваете две ссылки, и нет ничего, что могло бы вызвать автоматическую упаковку / распаковку.Если бы это было так, код, написанный на J2SE 1.4 и более ранних версиях, сломался бы.

...