昨天我有一个两个小时的技术电话面试(我通过了,哇哦!),但我完全掩盖了以下关于 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()
方法中的两个单独的打印语句: att1.equals(t3)
和t3.equals(t3)
. 后一种情况很明显,而前一种情况,即使t1
有一个Object类型的引用,它也被实例化为Test类型,所以动态绑定应该调用方法的覆盖形式。
显然不是。我的面试官鼓励我自己运行程序,你瞧,被覆盖的方法只有一个输出:在 line t3.equals(t3)
。
那么我的问题是,为什么?正如我已经提到的,即使t1
是 Object 类型的引用(因此静态绑定会调用 Object 的equals()
方法),动态绑定应该注意根据引用的实例化类型调用最具体的方法版本。我错过了什么?