Это гарантируется, что новое целое число (i) == я в Java?
-
26-09-2019 - |
Вопрос
Рассмотрим следующий фрагмент:
int i = 99999999;
byte b = 99;
short s = 9999;
Integer ii = Integer.valueOf(9); // should be within cache
System.out.println(new Integer(i) == i); // "true"
System.out.println(new Integer(b) == b); // "true"
System.out.println(new Integer(s) == s); // "true"
System.out.println(new Integer(ii) == ii); // "false"
Очевидно, почему последняя строка будет ВСЕГДА принты "false"
: мы используем ==
Справочная идентичность сравнения и new
объект будет НИКОГДА быть ==
на уже существующий объект.
Вопрос о первых 3 линиях: это сравнения гарантировано быть на примитиве int
, с Integer
Auto-Unboxed? Есть ли случаи, когда примитив будет автоматически в штучной упаковке, и выполняются ссылочные сравнения личности? (что бы все тогда было false
!)
Решение
Да. JLS §5.6.2 Определяет правила для двоичного числового продвижения. Частично:
Когда оператор применяет двоичную числовую продвижение в пару операндов, каждый из которых должен обозначать значение, которое преобразуется в числовом типе, применяются следующие правила, в порядке, используя преобразование расширения (§5.1.2) для преобразования операндов по мере необходимости :
Если какой-либо из операндов имеет ссылочный тип, преобразование Unboxing (§5.1.8) выполняется.
Двоичная числовая продвижение применяется для нескольких числовых операторов, включая «операторы численного равенства == и! =».
JLS §15.21.1 (Операторы численного равенства == и! =) Указывает:
Если операнды оператора равенства являются оба числовым типом, либо один имеет числовой тип, а другой - это кабриолет (§5.1.8) к числовому типу, двоичное числовое продвижение выполняется на операндах (§5.6.2).
В противоположность, JLS §15.21.3 (Операторы ссылочного равенства == и! =) Предусматривает:
Если операнды оператора равенства являются оба типа ссылочного типа, либо тип нулевого типа, то операция является объектом равенства
Это соответствует общему пониманию бокса и распаковки, это только, только когда есть несоответствие.
Другие советы
Я сначала объясню точно, когда ==
это опорное равенство, а также точно, когда Это числовое равенство. Условия для справочного равенства проще, поэтому она будет объяснена первым.
JLS 15.21.3 Операторы ссылочного равенства ==
и !=
Если операнды оператора равенства являются оба типа ссылочного типа, либо нулевой Тип, то операция является объектом равенства.
Это объясняет следующее:
System.out.println(new Integer(0) == new Integer(0)); // "false"
Обе операнды есть Integer
, которые являются ссылочными типами, и поэтому ==
это справочное сравнение равенства и два new
Объекты никогда не будут ==
друг другу, так вот почему он печатает false
.
За ==
быть численным равенством, по крайней мере один из операндов должен быть числовым типом; Это указано следующим образом:
JLS 15.21.1 Операторы численного равенства ==
и !=
Если операнды оператора равенства являются оба числового типа или один числового типа и другой кабриолет к числовому типу, двоичное числовое продвижение проводится на операндах. Если продвинутый тип операндов
int
илиlong
, тогда проведен тест целочисленного равенства; Если продвинутый типfloat or
Двойной`, затем проводится тест на равенство с плавающей точкой.Обратите внимание, что двоичное числовое продвижение выполняет преобразование набора значений и преобразование Unboxing.
Таким образом, рассмотрим следующее:
System.out.println(new Integer(0) == 0); // "true"
Это отпечатки true
, так как:
- правильный операнд является численность
int
тип - левый операнд является конвертируемым числовой тип, распадающийся в
int
- поэтому
==
является операцией численного равенства
Резюме
- Если обе операнды
==
и!=
являются ссылочными типами, он всегда будет ориентировочным равенством- Неважно, если операнды конвертируются в числовых типах
- Если хотя бы один из операндов является числовым типом, он всегда будет операциями численного равенства
- Auto-Unboxing на одном (не более!) Операндов будет выполняться при необходимости
Рекомендации
- JLS 4.2. Примитивные типы и ценности
- " Числовые типы являются интегральными типами и типы плавающих точек. "
- Java Language Guide / AutoBoxing
- JLS 5.1.8 Преобразование Unboxing
- JLS 15.21.1 Операторы численного равенства
==
и!=
- JLS 15.21.3 Операторы ссылочного равенства
==
и!=
- JLS 5.6.2 Двоичное числовое Продвижение