Сравнение примитивных оберток

Возможный дубликат:
Использование == оператор в Java для сравнения объектов-оболочек

java версии 1.6.0_26

Из книги по подготовке к экзамену SCJP:

В целях экономии памяти два экземпляра следующих [Short и Integer из -128 и 127, а также некоторые другие, но не имеют значения для вопроса] объекты-оболочки (созданные посредством boixng) всегда будут ==, когда их примитивные значения совпадают.

Что я сделал:

Если мы сравним два целых числа от -128 до 127 следующим образом:

1. Integer i1 = 10;
2. Integer i2 = 10;
3. System.out.println(i1 == i2); // true

Но почему то же самое дает нам «ложь» или, может быть, это не одно и то же:

4. Integer i3 = new Integer(10);
5. Integer i4 = new Integer(10);
6. System.out.println(i3 == i4); // false

Мои вопросы:

1) Делаем ли мы в 1-й строке кода неявный бокс?

2) Почему 3-я и 6-я строки кода дают разные результаты?


person user485553    schedule 27.12.2012    source источник
comment
Ты прав! Это дубликат.   -  person user485553    schedule 27.12.2012


Ответы (4)


Делаем ли мы в 1-й строке кода неявный бокс?

Yes

2) Почему 3-я и 6-я строки кода дают разные результаты?

Integer.valueOf(int) объединяет все значения от -128 до 127.

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

фрагмент кода из Integer.java:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

Вместо этого, когда вы вызываете new Integer(10);, он создает совершенно новый объект, поэтому два разных объекта с одинаковыми целочисленными значениями будут указывать на разные адреса памяти.

person Rahul    schedule 27.12.2012
comment
Итак, если я напишу Integer i1 = 10; компилятор неявно заменяет его на Integer i1 = Integer.valueOf(10); А это значит, что если мое число в диапазоне от -128 до 127 (или ваше IntegerCache.high) мне выдает уже существующий объект Integer. И это основная причина, по которой мы получаем истину при сравнении ==. - person user485553; 27.12.2012

1) Does on the 1st line of code we make implicit boxing?

да. Он называется Auto-Boxing.

2) Why the 3rd and 6th lines of code give us different results?

== фактически проверяет, имеют ли две переменные точно такое же значение. Обратите внимание, что примитивная переменная содержит то, что вы видите, а ссылочная переменная содержит адрес объекта, который она содержит.

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

System.out.println(i1 == i2);

Будет правдой.

Но в строке 6.

System.out.println(i3 == i4);

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

System.out.println(i3.equals(i4));
person Jayamohan    schedule 27.12.2012

В вашем первом примере компилятор использует бокс для назначения переменных. В этом случае i1/i2 являются константами (немного похожими на статические конечные объекты).

Во втором примере вы создаете два экземпляра Integer, поэтому они никогда не бывают одинаковыми.

person asgoth    schedule 27.12.2012

Строка 6 показывает false, потому что она сравнивается, чтобы увидеть, указывают ли ссылки i3 и i4 на один и тот же объект! В данном случае это не так. следовательно, false.

Автоупаковка и распаковка вступают в игру, если задействованы как обертки, так и примитивы. Здесь и i3, и i4 являются объектами-оболочками, поэтому они будут рассматриваться как любые другие POJO.

AutoBoxing происходит только в том случае, если задействованы как объекты-оболочки, так и примитивы,

Например

int primitive = 10;
Integer wrapper = new Integer(10);
System.out.println(primitive == wrapper); //true

печатает True в приведенном выше сравнении == значение примитива сравнивается с состоянием оболочки.

person codeMan    schedule 27.12.2012
comment
Я понимаю, что он сравнивает две ссылки. Но я не понимаю, зачем это делать? - person user485553; 27.12.2012