Вчера у меня было двухчасовое собеседование по телефону по техническим вопросам (которое я прошел, у-у-у!), Но я полностью замолчал следующий вопрос, касающийся динамического связывания в 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()
объекта), динамическая привязка должна позаботиться о вызове наиболее конкретной версии метода на основе созданного экземпляра тип ссылки. Что мне не хватает?