Сравнение символов, целых чисел и аналогичных типов в Java: используйте equals или ==?

Я хотел убедиться в чем-то в Java: Если у меня есть Символ или Целое число или Длинный и такие вещи, следует ли использовать равные или достаточно?

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

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

Ответ 1

EDIT: спецификация дает некоторые гарантии для преобразования бокса. Из раздел 5.1.7:

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

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

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

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

if (foo.equals(bar))

или

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

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

Ответ 2

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

Даже (и особенно), если эти объекты являются примитивными типами обложек: Byte, Character, Short, Integer, Long, Float, Double и Boolean.

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

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

  • все значения, участвующие в сравнении, являются примитивными типами (и предпочтительно не числами с плавающей запятой).
  • вы действительно хотите знать, ссылаются ли на две ссылки на один и тот же объект (это включает сравнение enum s, потому что это значение привязано к идентификатору объекта)

Ответ 3

//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 или сравнивать их примитивные значения.

Ответ 4

Java Language Spec 5.1.7:

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

и

Обсуждение

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

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

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

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

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

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

Ответ 5

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

if(this == o) return true;

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

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

*, конечно, есть несколько раз, когда вы не должны принимать этот совет.

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

  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
  }

Ответ 9

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

Примеры:

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

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

public enum Gender {
    MALE, FEMALE;
}

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