Ответ 1
Короткий ответ
Ключевым моментом является следующее:
-
==
между двумя ссылочными типами всегда используется сравнение ссылок- Чаще всего нет. с
Integer
иString
, вы хотите использоватьequals
вместо
- Чаще всего нет. с
-
==
между ссылочным типом и числовым примитивным типом всегда является числовое сравнение- Тип ссылки будет подвергнут распаковке преобразования
- Unboxing
null
всегда бросаетNullPointerException
- В то время как Java имеет множество специальных процедур для
String
, на самом деле это НЕ примитивный тип
Вышеприведенные утверждения сохраняются для любого допустимого Java-кода. При таком понимании в представленном фрагменте нет никакой несогласованности.
Длительный ответ
Вот соответствующие разделы JLS:
JLS 15.21.3 равенство ссылок Операторы
==
и!=
Если операнды оператора равенства являются либо ссылочным типом, либо нулевым типом, то операция является равенством объекта.
Это объясняет следующее:
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"
Для ==
для численного равенства по крайней мере один из операндов должен быть числовым:
JLS 15.21.1 Операторы численного равенства
==
и!=
Если операнды оператора равенства и числового типа, или один числового типа, а другой - конвертируемый в числовой тип, двоичное числовое продвижение выполняется в операндах. Если продвинутый тип операндов
int
илиlong
, то выполняется целочисленный тест равенства; если продвинутый типfloat or
double`, то выполняется тест равенства с плавающей запятой.Обратите внимание, что двоичное числовое продвижение выполняет преобразование набора значений и преобразование распаковки.
Это объясняет:
Integer i = null;
if (i == 0) { //NullPointerException
}
Вот выдержка из Effective Java 2nd Edition, Item 49: Предпочитайте примитивы для примитивов в штучной упаковке:
В общем, используйте примитивы, предпочитая вложенные в бокс примитивы, когда у вас есть выбор. Примитивные типы проще и быстрее. Если вы должны использовать примитивы в штучной упаковке, будьте осторожны! Автобоксинг уменьшает многословие, но не опасность использования примитивов в штучной упаковке. Когда ваша программа сравнивает два вставных примитива с оператором
==
, он выполняет сравнение идентичности, что почти наверняка не то, что вы хотите. Когда ваша программа выполняет смешанные вычисления с использованием примитивов с боксами и unboxed, она распаковывается, а когда ваша программа распаковывается, она может бросатьNullPointerException
. Наконец, когда ваши программные коды приносят примитивные значения, это может привести к дорогостоящим и ненужным созданиям объектов.
Есть места, где у вас нет выбора, кроме как использовать вставные примитивы, например. дженериков, но в противном случае вам следует серьезно подумать, оправдано ли решение использовать примитивы в штучной упаковке.
Ссылки
- JLS 4.2. Примитивные типы и ценности
- "Числовые типы - это интегральные типы и типы с плавающей запятой."
- JLS 5.1.8 Конвертирование Unboxing
- "Тип называется преобразованным в числовой тип, если он является числовым типом, или он является ссылочным типом, который может быть преобразован в числовой тип путем распаковки преобразования".
- "Unboxing conversion преобразует [...] из типа
Integer
в типint
" - "Если
r
равноnull
, распаковка конверсии вызываетNullPointerException
"
- Руководство по языку Java/Автобоксинг
- JLS 15.21.1 Операторы численного равенства
==
и!=
- JLS 15.21.3 равенство ссылок Операторы
==
и!=
- JLS 5.6.2 Двоичное числовое продвижение
Связанные вопросы
- При сравнении двух
Integers
в Java происходит автоматическое разблокирование? - Почему эти
==
, но неequals()
? - Java: В чем разница между автобоксингом и литьем?
Связанные вопросы
- В чем разница между int и Integer в Java/С#?
- Гарантируется ли что новый Integer (i) == я в Java? (ДА!!! Ящик распакован, а не наоборот!)
- Почему
int num = Integer.getInteger("123")
throwNullPointerException
? (!!!) - Java noob: generics over objects only? (да, к сожалению)
- Java
String.equals
по сравнению с==