Wczoraj odbyłem dwugodzinny telefoniczny wywiad techniczny (który zdałem, woohoo!), Ale całkowicie stłumiłem następujące pytanie dotyczące dynamicznego wiązania w Javie. Jest to podwójnie zagadkowe, ponieważ uczyłem tego pojęcia studentom, kiedy byłem asystentem kilka lat temu, więc perspektywa, którą podałem im dezinformację, jest trochę niepokojąca ...
Oto problem, który mi dano:
/* 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);
}
}
Zapewniłem, że wynikiem powinny być dwie oddzielne instrukcje print z nadpisanej equals()
metody: at t1.equals(t3)
i t3.equals(t3)
. Ten drugi przypadek jest wystarczająco oczywisty, a w pierwszym przypadku, mimo że t1
ma odwołanie do typu Object, jest on tworzony jako test typu, więc dynamiczne wiązanie powinno wywołać przesłoniętą formę metody.
Najwyraźniej nie. Mój ankieter zachęcił mnie, abym sam uruchomił program, a oto wynik z nadpisanej metody był tylko jeden: na linii t3.equals(t3)
.
Moje pytanie brzmi więc, dlaczego? Jak już wspomniałem, mimo że t1
jest referencją typu Object (więc statyczne wiązanie wywołałoby equals()
metodę Object ), dynamiczne wiązanie powinno zadbać o wywołanie najbardziej szczegółowej wersji metody opartej na instancji typu odwołania. czego mi brakuje?