Подтвердить что ты не робот

Метод equals() в Java неожиданно работает на длинном типе данных

Сначала рассмотрим следующие выражения в Java.

Integer temp = new Integer(1);
System.out.println(temp.equals(1));

if(temp.equals(1))
{
     System.out.println("The if block executed.");
}

Все эти утверждения работают нормально. В этом нет никаких сомнений. Выражение temp.equals(1) оценивается как true, как ожидалось, и поэтому выполняется только оператор внутри блока if.


Теперь, когда я изменяю тип данных от Integer до Long, оператор temp1.equals(1) неожиданно оценивается как false следующим образом.

Long temp1 = new Long(1);
System.out.println(temp1.equals(1));

if(temp1.equals(1))
{
    System.out.println("The if block executed.");
}

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

Выражение temp1.equals(1) оценивается как false, и, следовательно, единственный оператор в блоке if не выполняется, чем обратное предыдущим операторам. Как?

4b9b3361

Ответ 1

Вы сравниваете Long с int. В javadoc для java.lang.Long#equals говорится, что метод equals

Сравнивает этот объект с указанным объектом. Результат является истинным тогда и только тогда, когда аргумент не является нулевым и является объектом Long, который содержит такое же длинное значение, что и этот объект.

Вместо этого попробуйте System.out.println(new Long(1).equals(1L)); Теперь, когда вы сравниваете Long с Long вместо Long с Integer, он печатает true.

Ответ 2

Литеральное значение 1 не является long, это a int. Вместо этого попробуйте использовать приведенный выше код:

System.out.println(temp1.equals(1L));

и

if (temp1.equals(1L))

Как вы можете видеть, добавление L после литерального значения 1 означает, что это a long, а затем сравнения работают как ожидалось.

Ответ 3

Причина, по которой вы можете сделать это сравнение, связана с автобоксированием в Java.

Фактический метод, который вы вызываете, таков:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Long.html#equals(java.lang.Object)

который сравнивает ваш объект Long с каким-либо другим объектом, а не с фактическим примитивным int.

Что происходит при вызове метода, так это то, что ваш примитив integer(1) автобоксирован в Object(Integer), после чего вы фактически вызываете:

new Long(1).equals(new Integer(1));

поэтому он терпит неудачу.

Вот почему, если вы вызываете

new Long(1).equals(1L) 

это сработало бы, потому что Java будет автобокс 1L (примитивный long, not int) в объект long, а не объект Integer.

Ответ 4

Согласно странице Javadoc на Long, .equals метод оценивается true только в том случае, если

  • Аргумент - это объект Long
  • Если (1) истинно, то объекты Long должны иметь равные значения

В вашем сценарии 1 есть объект int, а не Long, поэтому он терпит неудачу (1) и, следовательно, оценивает значение false. Если вам нужно проверить значение Long, используйте 1L.

Ответ 5

Java ленив.

Когда вы выполните следующее сравнение, java автоматически перенесет int в long (поскольку long может содержать любое значение, которое может содержать int). И сравнение между двумя длинными, а не двумя ints.

int i = 1;
long l = 1L;
boolean b = i == l;

Java может это сделать, потому что информация о типе о i и l известна во время компиляции и при выполнении сравнения. Однако, когда вы используете коробчатую версию, тип может быть известен во время компиляции, но не при выполнении сравнения. Это связано с тем, что сравнение должно выполняться в методе equals, а поскольку equals принимает Object как параметр, информация о типе теряется. Таким образом, Java ленив и проверяет только, равны ли два бокс-номера, если они оба являются экземплярами одного класса Number (например, Integer или Long, или Double, и т.д.).

Вызывает единственный полностью надежный способ сравнения двух чисел неизвестного типа во время выполнения - это преобразовать оба значения в строки и оба в BigDecimal, а затем использовать метод compareTo (и не). Хотя, если вы знаете, что вы когда-либо будете получать долги и ints, тогда жизнь проще, поскольку вы можете просто сделать следующее.

Number n0 = new Long(1L);
Number n1 = new Integer(1);
boolean equal = n0.longValue() == n1.longValue();

Ответ 6

Это поведение согласуется с autoboxing, преобразующим 1 в Integer, который затем сравнивается с другим Integer(1). Сравнение a Long с a Integer дает false.

Если вы использовали бы 1L для сравнения с Long, он дал бы true.

Ответ 7

Длинные temp1 = новые Длинные (1); System.out.println(temp1.equals(1));

if (temp1.equals(1)) {     System.out.println( "Выполняется блок if" ); }

в этом коде temp1.equals(1) сравнивается объект Long с объектом Integer, который дает результат false, мы можем исправить его, используя 1L вместо 1,, eg temp1.equals(1L), мы сравниваем объект Long с Long и получаем результат TRUE

Ответ 8

Реализация equals() метод класса Long иллюстрирует, почему:

public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}

Ответ 9

Метод equals в Java.lang.Long сначала начинается с проверки экземпляра SingleOff только после этого, когда сравнивается значение.

public boolean equals(Object obj) {
     if (obj instanceof Long) {
         return value == ((Long)obj).longValue();
     }         
     return false;
}

Итак, если вы собираетесь использовать, а Integer Value - в месте длинного значения, тогда первая проверка завершится неудачно и, следовательно, вы получите false в качестве результата.

Ответ 10

Вы можете сравнивать значения Long/integer без ut equals(). Это необходимо, только когда вы сравниваете строки, насколько мне известно.