Краткий ответ
Ключевой момент таков:
==
между двумя ссылочными типами всегда является сравнительным сравнением
- Чаще всего, например, нет. с
Integer
и String
вы хотите использовать equals
вместо
==
между ссылочным типом и числовым типом примитива всегда является числовым сравнением
- Ссылочный тип будет подвергнут распаковке.
- Распаковка
null
всегда выбрасывает NullPointerException
- Хотя в Java есть много специальных обработок для
String
, на самом деле это НЕ примитивный тип
Вышеприведенные операторы верны для любого данного действительного Java-кода. При таком понимании нет никаких противоречий в представленном вами фрагменте.
Длинный ответ
Вот соответствующие разделы JLS:
Если операнды оператора равенства имеют тип ссылки или тип null , то операция является равенством объектов.
Это объясняет следующее:
Integer i = null;
String str = null;
if (i == null) { // Nothing happens
}
if (str == null) { // Nothing happens
}
if (str == "0") { // Nothing happens
}
Оба операнда являются ссылочными типами, и поэтому ==
является сравнением равенства ссылок.
Это также объясняет следующее:
System.out.println(new Integer(0) == new Integer(0)); // "false"
System.out.println("X" == "x".toUpperCase()); // "false"
Чтобы ==
было числовым равенством, хотя бы один из операндов должен иметь числовой тип :
Если операнды оператора равенства равны и числового типа, или , то один числового типа, а другой преобразуемый в числовой тип, двоичный числовое продвижение выполняется по операндам. Если расширенный тип операндов - int
или long
, то выполняется проверка на целочисленное равенство; если повышенный тип равен float or
double`, то выполняется тест на равенство с плавающей точкой.
Обратите внимание, что двоичное числовое продвижение выполняет преобразование набора значений и распаковку.
Это объясняет:
Integer i = null;
if (i == 0) { //NullPointerException
}
Вот выдержка из Effective Java 2nd Edition, Item 49: Предпочтение примитивов примитивам в штучной упаковке :
В итоге, используйте примитивы вместо коробочных примитивов, когда у вас есть выбор. Примитивные типы проще и быстрее. Если вы должны использовать коробочные примитивы, будьте осторожны! Автобокс уменьшает многословность, но не опасность использования коробочных примитивов. Когда ваша программа сравнивает два коробочных примитива с оператором ==
, она выполняет сравнение идентификаторов, что почти наверняка не то, что вам нужно. Когда ваша программа выполняет вычисления смешанного типа с использованием упакованных и распакованных примитивов, она выполняет распаковку, а когда ваша программа выполняет распаковку, она может выдать NullPointerException
. Наконец, когда ваша программа упаковывает примитивные значения, это может привести к дорогостоящим и ненужным созданиям объектов.
Есть места, где у вас нет выбора, кроме как использовать примитивы в штучной упаковке, например генерики, но в противном случае вам следует серьезно подумать, оправдано ли решение использовать коробочные примитивы.
Ссылки
Смежные вопросы
Смежные вопросы