Java 动态绑定和方法重写

2022-08-31 11:24:04

昨天,我进行了两个小时的技术电话面试(我通过了,哇哦!),但我完全理解了以下关于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);
  }
}

我断言输出应该是来自重写方法中的两个单独的 print 语句:at 和 。后一种情况已经足够明显了,对于前一种情况,即使具有 Object 类型的引用,它也被实例化为 Test 类型,因此动态绑定应调用该方法的重写形式。equals()t1.equals(t3)t3.equals(t3)t1

显然不是。我的面试官鼓励我自己运行程序,瞧,被覆盖的方法只有一个输出:在行 。t3.equals(t3)

那么我的问题是,为什么?正如我已经提到的,即使它是 Object 类型的引用(因此静态绑定将调用 Object 的方法),动态绑定也应该负责基于引用的实例化类型调用方法的最特定版本。我错过了什么?t1equals()


答案 1

Java 对重载方法使用静态绑定,对重写方法使用动态绑定。在示例中,equals 方法是重载的(具有与 Object.equals()不同的参数类型),因此调用的方法在编译时绑定到引用类型。

这里有一些讨论

它是等式方法的事实并不真正相关,除了重载而不是覆盖它是一个常见的错误,你已经意识到这是基于你在面试中对问题的回答。

编辑:这里也有一个很好的描述。此示例显示与参数类型相关的类似问题,但由相同的问题引起。

我相信如果绑定实际上是动态的,那么调用方和参数是 Test 实例的任何情况都会导致被覆盖的方法被调用。因此,t3.equals(o1) 将是唯一不会打印的情况。


答案 2

的方法不会覆盖 的方法。查看参数类型!该类使用接受 .equalsTestequalsjava.lang.ObjectTestequalsTest

如果该方法旨在重写,则应使用@Override批注。这将导致编译错误指出此常见错误。equals


推荐