Может ли .equals быть переопределено так, что a.equals(a) возвращает false?
Я все еще довольно свежий для всего этого, но я работаю над получением моего сертификата OCAJP (Java). Я вспомнил, что ранее читал, что метод .equals можно переопределить, когда я пришел к этому вопросу:
![Вопрос из подготовительных материалов Enthuware:]()
Теперь эти вопросы были довольно злыми, насколько мне известно. Скручивайте каждую мелочь, которую, как вы думаете, знаете, чтобы заставить вас узнать все мелочи. Теперь я догадался, E, но я не думал, что D был прав. Я имею в виду 99,9% времени, конечно, но я думал, что это вопрос с трюком, основанный на формулировке.
Это заставило меня думать, это правда? Я имею в виду, если я задам вопрос на экзамене, я знаю, как ответить на него сейчас, но в глубокой темной бездне переопределения безумия можно ли создать ситуацию, когда a.equals(a) возвращает false? Я чувствую, что это сделает Аристотеля сердитым...
Ответы
Ответ 1
Обратите внимание, что a
. b
и c
являются экземплярами примитивных классов-оболочек (таких как Integer, Double и т.д.). Эти классы являются окончательными и не могут быть расширены, поэтому вы не можете переопределить их реализацию equals
.
Поэтому a.equals(a)
всегда будет возвращать true, так как эти классы правильно реализуют equals
.
Ответ 2
Так как equals(...)
не является окончательным методом Object
, да, это очень хорошо возможно в другой ситуации.
@Override
public boolean equals(Object obj) {
return false;
}
Однако этот вопрос, в частности, говорит, что это примитивные обертки (например, Integer, Boolean и т.д.), и поскольку эти классы являются окончательными, вы не можете их расширять, поэтому a.equals(a)
всегда будет возвращать true
.
Ответ 3
Целое число a.equals(a) может возвращать false
Но вы должны быть действительно злыми и использовать отражения и многопоточность:
Если вы запустите этот код, есть вероятность, что гоночный режим может изменить внутреннее значение myInt
, пока происходит сравнение. Если вы хотите имитировать это условие, просто установите точку останова внутри Integer.intValue()
запустите код в отладке и нажмите continue. Это создаст задержку, которая искусственно создаст условие гонки, и консоль вернет false.
class IntegerEqualsTest
{
public static void main( final String[] args )
{
final Integer myInt = new Integer( 420 );
new Thread() {
public void run() {
try {
final Field f = Integer.class.getDeclaredField( "value" );
f.setAccessible( true );
f.setInt( myInt, 100 );
} catch( final Exception e ) {}
}; }.start();
System.out.println( myInt.equals( myInt ) );
}
}
Ответ 4
Другие ответы уже ответили на ваш вопрос - нет, это невозможно с классами примитивных классов Java.
Я попытаюсь рассмотреть "вопрос, стоящий за вопросом": возможно ли это с другими классами?
[...] в глубокой темной бездне переопределения безумия, возможно ли создать ситуацию, когда a.equals(a) возвращает false? Я чувствую себя так заставит Аристотеля рассердиться...
На самом деле это хороший вопрос, и ответ таков: "Да, можно создать такую ситуацию, и да, это сделает Аристотеля сердитым. На самом деле, я не знаю, может ли Аристотель рассердиться, не узнав его, но это наверняка вызовет много горя для того, кто должен работать с кодом.
Дело в том, что существует контракт, связанный с Object.equals()
:
Метод equals реализует отношение эквивалентности на непустых ссылки на объекты:
[...]
Это рефлексивно: для любого ненулевого опорного значения х, x.equals(х) должна возвращать верно.
Javadocs для Object.equals
Да, создавая свой собственный класс, вы можете нарушить этот контракт. Существует (к сожалению) ничего в компиляторе или время выполнения, останавливающее вас.
Однако много кода зависит от этого контракта, поэтому, если вы его нарушите, любой код, который использует equals
, скорее всего, не будет таинственным образом.
Один пример: собственные классы коллекции Java (java.util.Collection
и друзья) полагаются на equals
. Если экземпляр класса, который неправильно реализует equals
, помещается в коллекцию, происходят странные вещи, такие как коллекция, иногда содержащая экземпляр, а иногда и нет.
Ответ 5
Вы можете взглянуть на реализации всех примитивных оболочек, т.е. Integer, Boolean, Character и т.д.... вы увидите, что реализация верна.
Причина в том, что с равными один раз после проверок проверяется ссылочное равенство и x.equals(x), поскольку оба объекта и аргумент являются одним и тем же объектом.