Вопрос-ответ

How can I properly compare two Integers in Java?

Как я могу правильно сравнить два целых числа в Java?

Я знаю, что если вы сравните заключенное в коробку примитивное целое число с константой, такой как:

Integer a = 4;
if (a < 5)

a будет автоматически распакован, и сравнение сработает.

Однако, что происходит, когда вы сравниваете два числа в штучной упаковке Integers и хотите сравнить либо равенство, либо меньше / больше, чем?

Integer a = 4;
Integer b = 5;

if (a == b)

Приведет ли приведенный выше код к проверке, являются ли они одним и тем же объектом, или в этом случае он будет автоматически распакован?

Как насчет:

Integer a = 4;
Integer b = 5;

if (a < b)

?

Переведено автоматически
Ответ 1

Нет, == between Integer, Long и т.д. Будет проверяться на ссылочное равенство - т.е.

Integer x = ...;
Integer y = ...;

System.out.println(x == y);

это проверит, относятся ли x и y к одному и тому же объекту, а не к равным объектам.

Итак

Integer x = new Integer(10);
Integer y = new Integer(10);

System.out.println(x == y);

гарантированно выводится false. Интернирование "маленьких" автоматически вставленных значений может привести к сложным результатам:

Integer x = 10;
Integer y = 10;

System.out.println(x == y);

Это будет напечатано true в соответствии с правилами бокса (раздел 5.1.7 JLS). По-прежнему используется равенство ссылок, но ссылки действительно равны.


Если значение p, помещаемое в ячейку, является целочисленным литералом типа int между -128 и 127 включительно (§3.10.1), или логическим литералом true или false (§3.10.3), или символьным литералом между '\ u0000' и '\u007f' включительно (§3.10.4), то пусть a и b являются результатами любых двух упаковочных преобразований p. Всегда бывает, что a == b.


Лично я бы использовал:

if (x.intValue() == y.intValue())

или

if (x.equals(y))

Как вы сказали, для любого сравнения типа оболочки (Integer, Long и т.д.) И числового типа (int, long и т.д.) Значение типа оболочки распаковывается, и тест применяется к задействованным примитивным значениям.

Это происходит как часть продвижения двоичных чисел (раздел 5.6.2 JLS). Просмотрите документацию по каждому отдельному оператору, чтобы узнать, применяется ли он. Например, из документации для == и != (JLS 15.21.1):


Если операнды оператора равенства оба имеют числовой тип, или один имеет числовой тип, а другой преобразуется (§5.1.8) в числовой тип, для операндов выполняется двоичное числовое преобразование (§5.6.2).


и для <, <=, > и >= (JLS 15.20.1)


Тип каждого из операндов оператора числового сравнения должен быть типом, который можно преобразовать (§ 5.1.8) в примитивный числовой тип, в противном случае возникает ошибка времени компиляции. Двоичное числовое продвижение выполняется для операндов (§ 5.6.2). Если расширенный тип операндов - int или long , то выполняется сравнение целых чисел со знаком; если этот расширенный тип - float или double , то выполняется сравнение с плавающей запятой.


Обратите внимание, что ничто из этого не рассматривается как часть ситуации, когда ни один из типов не является числовым типом.

Ответ 2

Начиная с Java 1.7, вы можете использовать Objects.equals:

java.util.Objects.equals(oneInteger, anotherInteger);

Возвращает true, если аргументы равны друг другу, и false
в противном случае. Следовательно, если оба аргумента равны null, возвращается true
и если ровно один аргумент равен null, возвращается false. В противном случае,
равенство определяется с помощью метода equals первого аргумента
.


Ответ 3

== все равно будет проверять равенство объектов. Однако легко быть обманутым:

Integer a = 10;
Integer b = 10;

System.out.println(a == b); //prints true

Integer c = new Integer(10);
Integer d = new Integer(10);

System.out.println(c == d); //prints false

Ваши примеры с неравенствами будут работать, поскольку они не определены для объектов. Однако при == сравнении равенство объектов все равно будет проверяться. В этом случае, когда вы инициализируете объекты из коробочного примитива, используется один и тот же объект (как для a, так и для b). Это приемлемая оптимизация, поскольку коробочные классы примитивов неизменяемы.

Ответ 4

Мы всегда должны использовать метод equals () для сравнения двух целых чисел. Это рекомендуемая практика.

Если мы сравним два целых числа, используя ==, это сработает для определенного диапазона целых значений (целое число от -128 до 127) из-за внутренней оптимизации JVM.

Пожалуйста, посмотрите примеры:

Пример 1:

Integer a = 100;
Integer b = 100;

if (a == b) {
System.out.println("a and b are equal");
} else {
System.out.println("a and b are not equal");
}

В приведенном выше случае JVM использует значения a и b из кэшированного пула и возвращает один и тот же экземпляр объекта (следовательно, адрес памяти) integer object, и мы получаем, что оба они равны.Это оптимизация, которую JVM выполняет для определенных значений диапазона.

Случай 2: В этом случае a и b не равны, потому что они не входят в диапазон от -128 до 127.

Integer a = 220;
Integer b = 220;

if (a == b) {
System.out.println("a and b are equal");
} else {
System.out.println("a and b are not equal");
}

Правильный способ:

Integer a = 200;             
Integer b = 200;
System.out.println("a == b? " + a.equals(b)); // true
java