Сравнение символьных, целых и подобных типов в Java:Использовать равенства или ==?

StackOverflow https://stackoverflow.com/questions/735832

  •  09-09-2019
  •  | 
  •  

Вопрос

Я хотел кое-что убедиться в Java:Если у меня есть символ, целое число или длинное число и тому подобное, следует ли мне использовать равенство или достаточно ==?

Я знаю, что в случае со строками нет никаких гарантий, что существует только один экземпляр каждой уникальной строки, но я не уверен насчет других коробочных типов.

Моя интуиция подсказывает, что нужно использовать равные значения, но я хочу убедиться, что не теряю производительность впустую.

Это было полезно?

Решение

РЕДАКТИРОВАТЬ:Спецификация делает некоторый гарантии на конверсии бокса.От раздел 5.1.7:

Если значение p в штучной упаковке является истинной, false, байт, символ в диапазоне u0000 до u007f, или int или короткое число между -128 и 127, то пусть R1 и R2 будут результатами любых двух преобразований бокса. р.Это всегда тот случай, когда r1 == r2.

Реализация может используйте бассейн побольше, заметьте.

Я бы Действительно избегайте написания кода, который полагается на это.Не потому, что это может потерпеть неудачу, а потому, что это неочевидно — мало кто будет знать эту спецификацию так хорошо.(Раньше я думал, что это зависит от реализации.)

Вы должны использовать equals или сравнить основные значения, т.е.

if (foo.equals(bar))

или

if (foo.intValue() == bar.intValue())

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

Другие советы

Если вы хотите сравнить что-либо о значении какого-либо объекта, используйте .equals().

Даже (и особенно), если эти объекты представляют собой примитивные типы-оболочки: Байт, Символ, Короткий, Целочисленный, Длинный, Плавающий, Двойной и Логический.

"==" всегда сравнивает только идентичность объекта и вас, это очень, очень редко то, что вам нужно.И де-факто никогда не бывает того, что вы хотите, с примитивными обертками.

Используйте только == в одном из этих двух сценариев:

  1. все значения, участвующие в сравнении, являются примитивными типами (и желательно не числами с плавающей запятой)
  2. вы действительно хотите знать, относятся ли две ссылки к одному и тому же объекту (включая сравнение enums, потому что там значение привязано к идентификатору объекта)
//Quick test
public class Test {
  public static void main(String[] args) {
    System.out.println("Are they equal? "+ (new Long(5) == new Long(5)));
  }
}

Выход:

«Они равны?0"

Отвечать:

Нет, они не равны.Вы должны использовать .equals или сравнивать их примитивные значения.

Спецификация языка Java 5.1.7:

Если значение p в штучной упаковке является истинной, false, байт, символ в диапазоне u0000 до u007f, или int или короткое число между -128 и 127, то пусть R1 и R2 будут результатами любых двух преобразований бокса. р.Это всегда тот случай, когда r1 == r2.

и:

Обсуждение

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

Для других значений эта формулировка не имеет никаких предположений о идентификации шлаковых значений со стороны программиста.Это позволило бы (но не потребовать) совместное использование некоторых или всех этих ссылок.

Это гарантирует, что в наиболее распространенных случаях поведение будет желательным, не навязывая чрезмерного штрафа на производительность, особенно на небольшие устройства.Меньше ограниченных памятью реализации могут, например, кэшировать все символы и шорты, а также целые числа и длины в диапазоне -32K - +32K.

Таким образом, в некоторых случаях == будет работать, во многих других — нет.Всегда используйте .equals в целях безопасности, поскольку вы не можете (как правило) сообщить, как были получены экземпляры.

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

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

Реализации методаquals(Object o) почти всегда начинаются с

if(this == o) return true;

так что используя equals даже если == это правда, на самом деле это не сильно влияет на производительность.

Я рекомендую всегда* использовать equals метод на объектах.

*конечно, бывают случаи, когда вам не следует следовать этому совету.

Общий ответ нет, вы не можете быть уверены, что для одного и того же числового значения полученные объекты Long будут одинаковыми (даже если вы ограничитесь использованием Long.valueOf()).

Однако вполне возможно, что вы получите повышение производительности, сначала попробовав проверить равенство ссылок (используя ==), а затем, в случае неудачи, попробовав метод равенства().Все зависит от сравнительных затрат на дополнительный тест == и вызов метода...Ваш результат может отличаться, но стоит попробовать простой тест контура, чтобы увидеть, что лучше.

Стоит отметить, что значения автоупаковки будут использовать объект из пула, если они доступны.Вот почему (Целое число) 0 == (Целое число) 0, но (Целое число) 128 != (Целое число) 128 для Java 6u13

Мне нравится видеть результат визуально:

  public static void main(String[] args)
  {
        Integer a = 126; //no boxed up conversion, new object ref
        Integer b = 126; //no boxed up conversion, re-use memory address
        System.out.println("Are they equal? " + (a == b)); // true
        Integer a1 = 140; //boxed up conversion, new object
        Integer b1 = 140; //boxed up conversion, new object
        System.out.println("Are they equal? " + (a1 == b1)); // false
        System.out.println("Are they equal? " + (new Long(5) == new Long(5))); // false
  }

== сравнивает ссылку на объект, пока equals(Object obj) сравнивается на предмет равенства объектов. Если когда-либо может существовать более одного экземпляра объекта равенства затем вы должен использовать equals для сравнения равенства.

Примеры:

Integer i1 = new Integer(12345);
Integer i2 = new Integer(12345);

это разные экземпляры объектов, но они равны в соответствии с равенством Integer, поэтому вы должны использовать equals(Object obj)

public enum Gender {
    MALE, FEMALE;
}

в этом случае будет только один экземпляр FEMALE существует так == безопасно использовать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top