Я знаю, что если вы сравните в штучной упаковке примитив Integer с константой, такой как:
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)
?
java
integer
autoboxing
shmosel
источник
источник
==
вместоequals
дает правильный результат, это может быть связано с тем, что чисел в штучной упаковке интернированы или используются иным образом (предположительно, для оптимизации компилятора). Причиной задать этот вопрос является выяснение того, что происходит внутри, а не того, что происходит. (По крайней мере, именно поэтому я здесь.)Ответы:
Нет, == между Integer, Long и т. Д. Проверяет равенство ссылок - т.е.
это проверит,
x
иy
ссылаются ли на один и тот же объект, а не на равные объекты.Так
гарантированно печатать
false
. Стаж «небольших» автобоксированных значений может привести к сложным результатам:Это будет печатать
true
, в соответствии с правилами бокса ( JLS раздел 5.1.7 ). Это еще ссылка равенство используется, но ссылки действительно являются равными.Лично я бы использовал:
или
Как вы говорите, для любого сравнения между типом обертки (
Integer
иLong
т. Д.) И числовым типом (int
иlong
т. Д.) Значение типа обертки распаковывается и тест применяется к примитивным значениям.Это происходит как часть двоичного числового продвижения ( раздел 5.6.2 JLS ). Посмотрите на документацию каждого отдельного оператора, чтобы увидеть, применяется ли она. Например, из документов для
==
и!=
( JLS 15.21.1 ):и
<
,<=
,>
и>=
( ПСБ 15.20.1 )Обратите внимание, что ничего из этого не рассматривается как часть ситуации, когда ни один из типов не является числовым типом.
источник
x.compareTo(y) < 0
вместоx < y
?==
будет по-прежнему проверять равенство объектов. Легко быть обманутым, однако:Ваши примеры с неравенствами будут работать, так как они не определены для объектов. Однако при
==
сравнении равенство объектов все равно будет проверено. В этом случае, когда вы инициализируете объекты из коробочного примитива, используется один и тот же объект (как для a, так и для b). Это хорошая оптимизация, поскольку классы примитивных блоков неизменны.источник
200
, оба теста будут напечатаныfalse
.equals
вызова».Начиная с Java 1.7 вы можете использовать Objects.equals :
источник
==
проверяет равенство ссылок, однако при написании кода:Java является достаточно умны , чтобы использовать тот же непреложными для
a
иb
, таким образом , это правда:a == b
. Любопытно, я написал небольшой пример, чтобы показать, где Java прекращает оптимизацию таким образом:Когда я компилирую и запускаю это (на моей машине), я получаю:
источник
tl; dr мое мнение - использовать унарный
+
для запуска распаковки одного из операндов при проверке на равенство значений, и просто использовать математические операторы в противном случае. Обоснование следующее:Уже упоминалось, что
==
сравнение для сравненияInteger
идентичностей, что обычно не то, чего хочет программист, и что цель состоит в том, чтобы сделать сравнение значений; тем не менее, я немного научился тому, как сделать это сравнение наиболее эффективно, с точки зрения компактности, правильности и скорости выполнения кода.Я использовал обычную кучу методов:
и получил этот код после компиляции и декомпиляции:
Как вы можете легко видеть, метод 1 вызывает
Integer.equals()
(очевидно), что методы 2-4 приводят к абсолютно одинаковому коду , разворачивая значения с помощью.intValue()
и затем сравнивая их напрямую, а метод 5 просто вызывает сравнение идентификаторов, что является неправильным способом сравнить значения.Поскольку (как уже упоминалось, например, в JS)
equals()
возникают накладные расходы (это должно быть сделаноinstanceof
и при непроверенном приведении), методы 2-4 будут работать с точно такой же скоростью, заметно лучше, чем метод 1 при использовании в узких циклах, поскольку HotSpot не Вероятно, оптимизировать забросы иinstanceof
.Это очень похоже на другие операторы сравнения (например,
<
/>
) - они будут запускать распаковку, а использованиеcompareTo()
не будет - но на этот раз операция HS сильно оптимизируется, посколькуintValue()
это всего лишь метод получения (основной кандидат на оптимизацию).На мой взгляд, редко используемая версия 4 является наиболее лаконичным способом - каждый опытный разработчик C / Java знает, что унарный плюс в большинстве случаев равен приведению к
int
/,.intValue()
хотя для некоторых это может быть небольшим моментом WTF (в основном для тех, кто не использует унарный плюс в своей жизни), он, вероятно, показывает намерение наиболее четко и кратко - это показывает, что мы хотим получитьint
значение одного из операндов, заставляя другое значение также распаковать. Также неоспоримо наиболее похоже на обычноеi1 == i2
сравнение используется для примитивныхint
значений.Мой голос идет за
i1 == +i2
иi1 > i2
стиль дляInteger
объектов, как по причинам производительности, так и по соображениям согласованности. Это также делает код переносимым на примитивы, не изменяя ничего, кроме объявления типа. Использование именованных методов похоже на создание семантического шума, похожего на критикуемыйbigInt.add(10).multiply(-3)
стиль.источник
unary +
(унарный плюс), см., Например, stackoverflow.com/questions/2624410/…призвание
Будет работать большую часть времени, но это не всегда гарантирует работу, поэтому не используйте его.
Самый правильный способ сравнить два класса Integer на равенство, предполагая, что они названы «a» и «b», это вызвать:
Вы также можете использовать этот способ, который немного быстрее.
На моей машине 99 миллиардов операций заняли 47 секунд с использованием первого метода и 46 секунд с использованием второго метода. Вам нужно будет сравнить миллиарды значений, чтобы увидеть разницу.
Обратите внимание, что «а» может быть нулевым, поскольку это объект. Сравнение таким способом не вызовет исключение нулевого указателя.
Для сравнения больше и меньше, используйте
источник
if (a==b)
работает только для небольших значений и не будет работать большую часть времени.Мы всегда должны использовать метод equals () для сравнения двух целых чисел. Это рекомендуемая практика.
Если мы сравним два целых числа с использованием ==, это будет работать для определенного диапазона целочисленных значений (целое число от -128 до 127) из-за внутренней оптимизации JVM.
Пожалуйста, смотрите примеры:
Случай 1:
В приведенном выше случае JVM использует значения a и b из кэшированного пула и возвращает один и тот же экземпляр объекта (следовательно, адрес памяти) целочисленного объекта, и мы получаем, что оба они равны. Оптимизация JVM выполняется для определенных значений диапазона.
Случай 2: В этом случае a и b не равны, потому что они не находятся в диапазоне от -128 до 127.
Правильный путь:
Надеюсь, это поможет.
источник
В моем случае я должен был сравнить два
Integer
s для равенства, где они оба могли бы бытьnull
. Искал похожую тему, не нашел ничего элегантного для этого. Придумали простые полезные функции.источник
Потому что метод сравнения должен быть сделан на основе типа int (x == y) или класса Integer (x.equals (y)) с правым оператором
источник
этот метод сравнивает два целых числа с нулевой проверкой, см. тесты
источник
Objects.equals(x,y)
метод, а не использовать собственный.