2016-04-21 3 views
4

Я изо всех сил, чтобы понять это Koan:Почему object.equals (новый Integer (1)) равен true?

@Koan 
public void equalsMethodCanBeChangedBySubclassesToTestsIfTwoObjectsAreEqual() { 
    Object object = new Integer(1); 
    assertEquals(object.equals(object), true); 
    assertEquals(object.equals(new Integer(1)), __); 
    // Note: This means that for the class 'Object' there is no difference between 'equal' and 'same' 
    // but for the class 'Integer' there is difference - see below 
} 

Насколько я понимаю, потому что object является экземпляром класса Object, метод .equals() не были перезаписаны, и поэтому для проверки объекта равенства.

Если new Integer(1) создает новый экземпляр, то это должен быть отдельный объект для object. Следуя моему примеру, правильный ответ должен быть false, но только true делает этот пропуск. Где ошибка в моей логике?

Редактировать: Я понимаю, что целые числа между -128 и 127 кэшируются. Если мое понимание объекта object верное (как указано выше), то это не имеет значения.

+0

Возможный дубликат [Java: Целое число равно vs. ==] (http://stackoverflow.com/questions/3637936/java-integer-equals-vs) – sidgate

+3

@sidgate Нет, этот полностью не связан с "равно vs. == " – dasblinkenlight

+0

Не забудьте принять ответ. – Timmos

ответ

9

Целое отменяет equals и проверяет, если основной int равно int другого Integer например, и если да, то возвращает true. Причина, по которой вызывается метод Integer equals, а не тот, что у Object, заключается в том, что тип времени выполнения object является Integer.

Целое - это объект, но из-за переопределенного equals идентификатор объекта не используется.

Все следующие логические выражения вычисляются верно:

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

Теперь рассмотрим Autoboxing, который повторно использует примеры значений в диапазоне [-128,127]. Следующие утверждения о равенстве объектов все оценки в true:

1 == ((Integer) 1) 
    ((Integer) (-128)) == ((Integer) (-128)) // in autoboxing range 
    ((Integer) (+127)) == ((Integer) (+127)) // same 

    ((Integer) (-200)) != ((Integer) (-200)) // not autoboxing 
    ((Integer) (+200)) != ((Integer) (+200)) // same 

    ((Integer) (-128)) != (new Integer(-128)) // explicit new instance, so no autoboxing 
    ((Integer) (+127)) != (new Integer(+127)) // same 
+0

Итак, комментарий в koan '// Примечание: это означает, что для класса« Объект »нет разницы между« equal »и« same »на самом деле не показано в коане, потому что это фактически« Integer.equals () 'который называется? – jazzabeanie

+0

Исправить. Тип среды выполнения - Integer, поэтому вы не вызываете Object.equals, а Integer.equals. – Timmos

4

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

Если бы это было не так, как бы что-то вроде этой работы (где интерфейсы, участвующие не имеют реализации на всех):

Comparable<Integer> a = 1; 
Serializable b = 1; 
assertTrue(a.equals(b)); 

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

1

Если новый Integer (1) создает новый экземпляр, то он должен быть отдельный объект объекта.

Вот где вы ошибетесь. Новый экземпляр Integer(1) будет false для ==, но true для equals.

+0

@Thilo - Хороший звонок - удалены неверные комментарии. – OldCurmudgeon

2

Слышал (а) Dynamic Method Dispatch?

Когда вы используете ссылку суперкласса для ссылки на объект подкласса, и если подкласс имеет переопределенный метод, этот переопределенный метод будет вызван.

Следовательно, хотя вы используете Object object = new Integer(1);, при вызове equals на объект всегда будет звонить Integer.equals().

И Integer.equals() проверяет равенство целых чисел, не обязательно такую ​​же ссылку.

4

Насколько я понимаю, потому что object является экземпляром класса Object, метод .equals() не перезаписаны, и, следовательно, проверяет объект равенства.

У вас есть это совершенно неправильно. Хотя статический тип переменной object равен Object, он остается экземпляром Integer. Вот почему equals() перенаправлен на Integer, что дает правильный результат.

Назначение экземпляра переменной базового типа или интерфейсу, реализованному классом, не «разделяет» объект его поведения подкласса. В частности, экземпляр Integer сохраняет все свои поведения, реализованные в классе Integer, хотя вы присвоили экземпляр переменной переменной Object.

Смежные вопросы