Краткий ответ
Ключевой момент заключается в следующем:
==
between two reference types is always reference comparison
- More often than not, e.g. with
Integer
and String
, you'd want to use equals
instead
==
between a reference type and a numeric primitive type is always numeric comparison
- The reference type will be subjected to unboxing conversion
- Распаковка
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
}
Вот выдержка из Эффективное 2-е издание Java, правило 49: Предпочитайте примитивы в штучной упаковке:
Таким образом, используйте примитивы вместо примитивов в штучной упаковке, когда у вас есть выбор. Примитивные типы проще и быстрее. Если вы должны использовать примитивы в штучной упаковке, будьте осторожны! Автобокс снижает многословие, но не снижает опасность использования упакованных примитивов. Когда ваша программа сравнивает два упакованных примитива с оператором ==
, она выполняет сравнение идентичности, что почти наверняка не то, что вам нужно. Когда ваша программа выполняет вычисления смешанного типа с использованием упакованных и распакованных примитивов, она выполняет распаковку, а когда ваша программа выполняет распаковку, она может выбросить NullPointerException
. Наконец, когда ваша программа упаковывает примитивные значения, это может привести к созданию дорогостоящих и ненужных объектов.
Есть места, где у вас нет выбора, кроме как использовать коробочные примитивы, например дженерики, но в противном случае вам следует серьезно подумать, оправдано ли решение использовать упакованные примитивы.
использованная литература
Связанные вопросы
Связанные вопросы
person
polygenelubricants
schedule
28.07.2010