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

Может ли .equals быть переопределено так, что a.equals(a) возвращает false?

Я все еще довольно свежий для всего этого, но я работаю над получением моего сертификата OCAJP (Java). Я вспомнил, что ранее читал, что метод .equals можно переопределить, когда я пришел к этому вопросу:

Вопрос из подготовительных материалов Enthuware:

Теперь эти вопросы были довольно злыми, насколько мне известно. Скручивайте каждую мелочь, которую, как вы думаете, знаете, чтобы заставить вас узнать все мелочи. Теперь я догадался, E, но я не думал, что D был прав. Я имею в виду 99,9% времени, конечно, но я думал, что это вопрос с трюком, основанный на формулировке.

Это заставило меня думать, это правда? Я имею в виду, если я задам вопрос на экзамене, я знаю, как ответить на него сейчас, но в глубокой темной бездне переопределения безумия можно ли создать ситуацию, когда a.equals(a) возвращает false? Я чувствую, что это сделает Аристотеля сердитым...

4b9b3361

Ответ 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), поскольку оба объекта и аргумент являются одним и тем же объектом.