昨天,我有两个小时的电话技术的采访(其中我通过,呜呼!), 但我完全muffed了以下问题有关的动态结合。它是加倍的令人费解,因为我用来教授这一概念的大学生,当我还是个TA几年前,这样的前景,我给他们错误的信息是有点令人不安的...

这里是我的问题是:

/* 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 有一个参考的类型对象,这是实例类型的测试,这样的动态结合应该呼吁的复盖形式的方法。

显然不是。我记者鼓励我运行程序的自己,你瞧,只有一个单一的输出自复盖的方法:在线 t3.equals(t3).

我的问题是,为什么?正如我已经提到,即使 t1 是一个参考的对象类型(所以静态的结合会援引的对象 equals() 法)、动态的结合 应该 照顾援引最具体版本的方法基础上的实例类型的参考。我是什么丢失?

有帮助吗?

解决方案

Java使用静态用于重载的方法结合,以及用于动态重写那些结合。在示例中,equals方法过载(具有不同的参数类型比的Object.Equals()),所谓的该方法被结合到参考类型在编译时。

此处一些讨论

事实上,它是equals方法是不是真的相关,除了它是一个常见的错误是超负荷的,而不是覆盖它,你已经知道根据你的回答面试问题的。

编辑: 一个很好的说明这里为好。这个例子示出与参数类似的问题类型,而不是,但由相同的问题引起的。

我相信如果结合实际上是动态的,然后被调用,其中主叫用户和参数是测试的一个实例将导致重写的方法任何情况下。所以t3.equals(01)将是将不打印的唯一情况。

其他提示

equalsTest方法不会覆盖equalsjava.lang.Object方法。看看参数类型!所述Test类超载equals与接受一个Test的方法。

如果该equals方法旨在覆盖,它应该使用@Override注释。这将引起编译错误地指出这个常见的错误。

有趣的是,在Groovy代码(可以被编译为一个类文件),所有但其中一个通话将执行打印语句。 (在一个测试比较对象显然不会调用Test.equals(测试)函数)。这是因为常规DOES做完全动态类型。这是特别有意义的,因为它没有显式动态类型的变量。我看过一对夫妇的,这被认为是有害的地方,程序员预计常规做java的事情。

Java不支持在参数协方差,只有在返回类型。

在换句话说,而在为覆盖方法的返回类型可能是什么它是在被覆盖的一个子类型,即不是真参数。

如果您在Object等参数为对象,把任何东西在子类中其他的等于将过载,而不是一个重写的方法。因此,如该方法将被调用的唯一情况是,当静态类型的参数的是Test,如在T3的情况下

好运的面试过程!我喜欢在询问这些类型的问题,而不是我教我的学生平时的算法中/数据结构问题公司了记者的采访。

我想在一个事实,即equals()方法不符合标准的关键在于:它需要在另一测试对象,而不是对象的对象,因此不能重写equals()方法。这意味着你实际上只重载它做一些特别的东西时,它给了测试对象,同时赋予其对象对象调用的Object.Equals(对象o)。展望代码通过任何IDE显示两个的equals()方法来测试。

的方法过载,而不是覆盖。等于始终以一个对象作为参数。

顺便说一句,你对这个项目在Bloch的Effective Java的(你应该拥有的)。

注意到一些 动态结合 (DD)和 静态的结合(SB)在搜索后一段时间:

1.时执行:(Ref.1)

  • DB:在运行的时间
  • SB:编译器的时间

2.用于:

  • DB:压倒一切的
  • SB:超载(静态的,私人的,最终)(Ref.2)

参考:

  1. 执行意味着解决程序,其方法,更喜欢用
  2. 因为不能压倒一切的方法与改静态的、私人或最终
  3. http://javarevisited.blogspot.com/2012/03/what-is-static-and-dynamic-binding-in.html

如果添加的另一种方法,它覆盖,而不是过载它会解释在运行时动态绑定呼叫。

/ *这是下面的程序的输出是什么? * /

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);
    }
}

我发现有关动态与静态结合一个有趣的文章。它带有的一段代码用于模拟动态绑定。这使我的代码更具有可读性。

https://sites.google.com/site/jeffhartkopf/covariance

也参见该SO问题,密切相关:重写JAVA equals方法夸克

在回答这个问题:“为什么?”是的Java语言是如何定义的。

要引用上协变和逆变维基百科文章:

  

返回类型的协方差被实现   Java编程语言   版本J2SE 5.0。参数类型有   是完全一样的(不变)的   方法覆盖,否则   方法被重载用平行   定义来代替。

其他的语言是不同的。

这是非常清楚的,没有覆盖这里的概念。这是方法重载。 对象类的Object()方法利用了对象类型的基准参数和这个equal()方法采用的类型的测试的参考参数。

我会尝试通过两个实例是一些例子扩展的版本,我可以跨越网络来解释这个问题。

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);
    }
}

下面,用于与计数值0,1,2,和3线;我们有参考的的对象作为 O1 T1 equals()方法。因此,在编译时,从 Object.class 文件将被限定的equals()方法。 结果

然而,即使参考 T1 是<强>对象下,它具有 intialization 测试类的即可。 结果Object t1 = new Test();。 点击 因此,在运行时它调用public boolean equals(Object other)其是

  

重写方法

“在这里输入的图像描述”

现在,对于计数值作为4和6,它是又简单的说 T3 其具有参考初始化测试的是主叫equals()方法以如下参数对象引用,并且是

  

重载方法

OK!

  

再次以更好地了解编译器会调用什么方法,只是   点击方法和Eclipse将突出的类似方法   它认为类型将在编译时调用。如果它没有得到   称为在编译时间,那么这些方法是方法的一个例子   overridding。

“在这里输入的图像描述”

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top