Вчера у меня было двухчасовое техническое телефонное интервью (которое я пропустил, woohoo!), Но я полностью задал следующий вопрос относительно динамического связывания в Java. И это вдвойне озадачивает, потому что я преподавал эту концепцию студентам, когда я был ТА, несколько лет назад, поэтому перспектива, что я дал им дезинформацию, немного тревожит ...
Вот проблема, которую мне дали:
/* What is the output of the following program? */
public class Test {
public boolean equals( Test other ) {
System.out.println( "Inside of Test.equals" );
return false;
}
public static void main( String [] args ) {
Object t1 = new Test();
Object t2 = new Test();
Test t3 = new Test();
Object o1 = new Object();
int count = 0;
System.out.println( count++ );// prints 0
t1.equals( t2 ) ;
System.out.println( count++ );// prints 1
t1.equals( t3 );
System.out.println( count++ );// prints 2
t3.equals( o1 );
System.out.println( count++ );// prints 3
t3.equals(t3);
System.out.println( count++ );// prints 4
t3.equals(t2);
}
}
Я утверждал, что выводом должны были быть два отдельных оператора печати из переопределенного метода equals()
: в t1.equals(t3)
и t3.equals(t3)
. Последний случай достаточно очевиден, и в первом случае, даже если t1
имеет ссылку на тип Object, он создается как тип Test, поэтому динамическое связывание должно вызывать переопределенную форму метода.
Видимо, нет. Мой интервьюер посоветовал мне запустить программу самостоятельно, и вот, из переопределенного метода был только один выход: в строке t3.equals(t3)
.
Тогда мой вопрос: почему? Как я уже упоминал, несмотря на то, что t1
является ссылкой типа Object (поэтому статическое связывание будет вызывать метод equals()
объекта), динамическое связывание должно позаботиться о вызове наиболее конкретной версии метода, основанного на методе. на экземплярный тип ссылки. Чего мне не хватает?