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 .