Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java动态绑定和方法重写_Java_Inheritance_Dynamic Binding - Fatal编程技术网

Java动态绑定和方法重写

Java动态绑定和方法重写,java,inheritance,dynamic-binding,Java,Inheritance,Dynamic Binding,昨天我接受了两个小时的技术电话面试(我通过了,呜呜!),但我完全忘记了以下关于Java中动态绑定的问题。这让人倍感困惑,因为几年前当我还是助教的时候,我曾经教本科生这个概念,所以我给他们错误信息的前景有点令人不安 我遇到的问题是: /* What is the output of the following program? */ public class Test { public boolean equals( Test other ) { System.out.printl

昨天我接受了两个小时的技术电话面试(我通过了,呜呜!),但我完全忘记了以下关于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()
方法中的两个单独的print语句:at
t1.equals(t3)
t3.equals(t3)
。后一种情况很明显,对于前一种情况,即使
t1
有一个type-Object的引用,它被实例化为type-Test,因此动态绑定应该调用方法的重写形式

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


那么我的问题是,为什么?正如我已经提到的,即使
t1
是Object类型的引用(因此静态绑定将调用Object的
equals()
方法),动态绑定也应该根据引用的实例化类型调用方法的最具体版本。我缺少什么?

我认为关键在于equals()方法不符合标准:它接受另一个测试对象,而不是对象对象,因此没有重写equals()方法。这意味着您实际上只重载了它,以便在给它指定测试对象的同时调用object.equals(objecto)。通过任何IDE查看代码时,都应该显示两个equals()方法进行测试。

该方法是重载的,而不是重写的。Equals始终将对象作为参数


顺便说一句,你在Bloch的有效java中有一个项目(你应该拥有)。

测试的
equals
方法不会覆盖
java.lang.Object
equals
方法。看看参数类型!
Test
类使用接受
Test
的方法重载
equals


如果
equals
方法要覆盖,则应使用@override注释。这将导致一个编译错误来指出这个常见错误。

Java不支持参数中的协方差,只支持返回类型中的协方差

换句话说,尽管重写方法中的返回类型可能是重写方法中的返回类型的子类型,但对于参数来说,情况并非如此

若对象中equals的参数是Object,那个么将equals与子类中的任何其他对象放在一起将是重载的,而不是重写的方法。因此,调用该方法的唯一情况是当参数的静态类型为Test时,如T3的情况


祝你面试顺利!我很想在一家公司接受面试,该公司会问这些类型的问题,而不是我教学生的常见算法/数据结构问题

有趣的是,在Groovy代码(可以编译成类文件)中,除了一个调用之外,所有调用都将执行print语句。(将测试与对象进行比较显然不会调用Test.equals(Test)函数。)这是因为groovy完全是动态类型。这尤其令人感兴趣,因为它没有任何显式动态类型的变量。我在几个地方读到过,这被认为是有害的,因为程序员希望groovy做java的事情

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

一些讨论

事实上,它是equals方法并不是真正相关的,只是过载而不是覆盖它是一个常见的错误,根据你在面试中对问题的回答,你已经意识到了这一点

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


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

问题“为什么?”的答案是Java语言就是这样定义的

引述:

实现了返回型协方差 在Java编程语言中 J2SE5.0版。参数类型具有 完全相同(不变) 方法重写,否则 方法使用并行函数重载 而是定义


其他语言是不同的。

很明显,这里没有覆盖的概念。这是方法重载。
对象类的
Object()
方法采用类型对象的引用参数,此
equal()
方法采用类型测试的引用参数。

动态绑定(DD)和静态绑定̣̣(SB)搜索一段时间后注意:

1.定时执行:(参考1)

  • DB:在运行时
  • SB:编译时间
2.用于

  • DB:覆盖
  • SB:过载(静态、专用、最终)(参考2)
参考资料:

  • 执行平均解析程序,选择哪个方法
  • 因为不能用修饰符static、private或final重写方法

  • 我发现了一篇关于动态绑定和静态绑定的有趣文章。它附带了一段模拟dy的代码
    public class DynamicBinding {
        public boolean equals(Test other) {
            System.out.println("Inside of Test.equals");
            return false;
        }
    
        @Override
        public boolean equals(Object other) {
            System.out.println("Inside @override: this is dynamic binding");
            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);
        }
    }
    
    public class Test {
    
        public boolean equals(Test other) {
            System.out.println("Inside of Test.equals");
            return false;
        }
    
        @Override
        public boolean equals(Object other) {
            System.out.println("Inside of Test.equals ot type Object");
            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
            o1.equals(t2);
    
            System.out.println("\n" + count++); // prints 1
            o1.equals(t3);
    
            System.out.println("\n" + count++);// prints 2
            t1.equals(t2);
    
            System.out.println("\n" + count++);// prints 3
            t1.equals(t3);
    
            System.out.println("\n" + count++);// prints 4
            t3.equals(o1);
    
            System.out.println("\n" + count++);// prints 5
            t3.equals(t3);
    
            System.out.println("\n" + count++);// prints 6
            t3.equals(t2);
        }
    }