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