Перейти к основному содержимому

Сравнение длинных значений в Java

· 3 мин. чтения

1. Обзор

В этом кратком руководстве мы обсудим различные способы сравнения двух экземпляров Long . Подчеркнем проблемы, возникающие при использовании оператора сравнения ссылок ( == ).

2. Проблема с использованием сравнения ссылок

Long — это класс-оболочка для примитивного типа long . Поскольку они являются объектами, а не примитивными значениями, нам нужно сравнить содержимое экземпляров Long , используя .equals() вместо оператора сравнения ссылок (==).

В некоторых случаях нам может показаться, что == это нормально, но внешность обманчива. Учтите, что мы можем использовать == с меньшими числами:

Long l1 = 127L;
Long l2 = 127L;

assertThat(l1 == l2).isTrue();

но не с большими числами. В конечном итоге у нас возникнут проблемы, если значения выходят за пределы диапазона от -128 до 127, что приведет к совершенно другому и неожиданному результату:

Long l1 = 128L;
Long l2 = 128L;

assertThat(l1 == l2).isFalse();

Это связано с тем, что Java поддерживает постоянный пул для экземпляров Long между -128 и 127 .

Однако эта оптимизация не дает нам лицензии на использование ==. В общем случае два экземпляра в штучной упаковке, имеющие одно и то же значение примитива, не дают одной и той же ссылки на объект.

3. Использование .equals()

Одним из решений является использование .equals() . Это оценит содержимое (а не ссылку) обоих объектов:

Long l1 = 128L;
Long l2 = 128L;

assertThat(l1.equals(l2)).isTrue();

4. Объекты.равно()

Проблема с использованием equals() заключается в том, что нам нужно быть осторожными, чтобы не вызвать его для нулевой ссылки.

К счастью, есть служебный метод, безопасный для нулей, который мы можем использовать — Objects.equals () .

Посмотрим, как это работает на практике:

Long l1 = null;
Long l2 = 128L;

assertThatCode(() -> Objects.equals(l1, l2)).doesNotThrowAnyException();

Как мы видим, нам не нужно беспокоиться, если какой-либо из Long , который мы хотим сравнить, равен нулю.

Под капотом Objects.equals() сначала используется оператор == для сравнения, а если это не удается, используется стандартный метод equals().

5. Распаковка длинных значений

5.1. Использование метода .longValue()

Далее воспользуемся оператором сравнения «==», но безопасным способом. Класс Number имеет метод .longValue() , который разворачивает примитивное длинное значение:

Long l1 = 128L;
Long l2 = 128L;

assertThat(l1.longValue() == l2.longValue()).isTrue();

5.2. Приведение к примитивным значениям

Другой способ распаковать Longпривести объекты к примитивным типам. Поэтому мы извлечем примитивное значение, а затем сможем перейти к использованию оператора сравнения:

Long l1 = 128L;
Long l2 = 128L;

assertThat((long) l1 == (long) l2).isTrue();

Обратите внимание, что для метода .longValue() или использования приведения мы должны проверить, является ли объект нулевым . У нас может быть исключение NullPointerException , если объект имеет значение null .

6. Заключение

В этом коротком руководстве мы рассмотрели различные варианты сравнения длинных объектов. Мы проанализировали различия при сравнении ссылок на объекты или контент.

Как всегда, полный исходный код статьи доступен на GitHub .