как оператор равенства работает с данными примитивного и объектного типов

Я знаю, что это очень простой вопрос, но я хочу прояснить концепцию. Я хочу знать, как работает оператор == в случае примитивного и объектного типа. Например

Integer a = 1;
int b = 1;
System.out.println(a == b)

как a сравнивается с b, тогда как a содержит ссылку на объект, который содержит значение 1. Может ли кто-нибудь прояснить мне, как это работает внутри?


person Still Learning    schedule 19.03.2015    source источник
comment
Посмотрите ответы на этот вопрос, который тесно связан. Вы также можете прочитать об автоматической распаковке, который будет использоваться в коде, который вы процитировали.   -  person Dawood ibn Kareem    schedule 19.03.2015
comment
docs.oracle.com/javase/tutorial/java/data/autoboxing. html   -  person ha9u63ar    schedule 19.03.2015


Ответы (2)


Обычно оператор равенства в Java выполняет так называемое поверхностное сравнение. Другими словами, он сравнивает значения, содержащиеся в переменных. Теперь переменные примитивных типов данных содержат само значение, а ссылочные типы содержат ссылку на область кучи, в которой хранится фактическое содержимое. Это означает, что в вашем фрагменте кода int b будет храниться значение 1, а Integer a будет содержать адрес памяти фактического объекта Integer в куче.

Теперь в приведенном вами конкретном примере есть одна особенность. Целочисленный класс — специальный класс-оболочка, который оборачивает примитивные целочисленные типы. Компилятор может автоматически преобразовывать такие объекты-оболочки в примитивные типы (что называется упаковкой и распаковкой).

Давайте рассмотрим код шаг за шагом, чтобы сделать его понятным.

Integer a = 1;

Компилятор фактически заменяет следующий код этой строки:

Integer a = Integer.valueOf(1);

Статический метод valueOf возвращает экземпляр объекта-оболочки, который упаковывает предоставленное примитивное значение. Эта процедура, когда компилятор создает класс-оболочку из примитивного типа, называется упаковкой.

При использовании такой оболочки объект сравнивается с примитивной переменной с помощью оператора равенства

a == b

компилятор фактически меняет его на следующее:

a.intValue() == b;

где intValue возвращает значение примитива, обернутое объектом-оболочкой (что называется распаковкой), т. е. оно распаковывает значение примитива и делает выражение эквивалентным сравнению двух примитивов. Вот почему оператор равенства вернул true

person akhilless    schedule 19.03.2015

В вашем конкретном примере упакованный тип Integer будет распакован в примитивный тип int, а == будет сравнивать примитивы (т.е. true в вашем случае).

person Sergey Pauk    schedule 19.03.2015
comment
Это означает, что сначала происходит автоматическая распаковка, затем фактическое значение ((autounboxing)obj == val) сравнивается в памяти, а не ref == val. поправьте меня, если я неправильно понимаю. - person Still Learning; 19.03.2015
comment
Не уверен, что понял ваш комментарий, но вот спецификация для преобразования распаковки: docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.8 - person Sergey Pauk; 19.03.2015
comment
да, сравнение объекта-оболочки с примитивным типом приводит к распаковке, так что вы в конечном итоге сравниваете два примитивных значения, см. мой ответ - person akhilless; 19.03.2015