为什么要调用超类方法?

时间:2013-09-19 12:21:38

标签: java

class One { 
  public void doThing(One o) {System.out.println("One");}
}

class Two extends One{
  public void doThing(Two t) {System.out.println("Two");}
}

public class Ugly {
  public static void main(String[] args) {
    Two t = new Two();
    One o = t;
    o.doThing(new Two());
  }
}

结果:一个

class One { 
  public void doThing(One o) {System.out.println("One");}
}

class Two extends One{
  public void doThing(Two t) {System.out.println("Two");}
}

public class Ugly {
  public static void main(String[] args) {
    Two t = new Two();
    One o = t;
    t.doThing(new Two());
  }
}

结果:两个

我知道在运行时,即使对象引用属于超类类型,实际的对象类型也是已知的,并且将调用实际对象的方法。但是如果是这种情况,那么在运行时应该调用doThing(Two t)方法,而是调用超类方法doThing(One o)。如果有人解释,我会很高兴

在第二段代码中,它打印“Two”。

问题:从超类引用调用时,它正在调用doThing(One o) 从子类引用调用时,它调用doThing(Two o)

注意:我知道我超载而不是骑行。为了更清晰,我编辑了我的问题。

5 个答案:

答案 0 :(得分:12)

方法doThing()OneTwo中有不同的方法签名。

One.doThing(One one)
Two.doThing(Two two)

由于签名不匹配,Two.doThing(Two)不会覆盖One.doThing(One),而o的类型为One,因此会调用One.doThing()

另外需要注意的是,One.doThing(One)可以将instance of Two作为One.doThing(One)的参数Two extends One

  

基本上,“@ nachokk - 你正在超载,而不是覆盖”

在第一个场景中,当你做到了

Two t = new Two();
One o = t;
o.doThing(new Two());

因此,oOne的一个实例,Two.doThing(Two)无法使用o因此调用One.doThing(One)

在第二种情况下,

Two t = new Two();
One o = t;
t.doThing(new Two());

tTwo的一个实例,因此会调用Two.doThing(Two)

答案 1 :(得分:1)

正如你所说的那样,你只是超载

    Two t = new Two();
    One o = t;
    o.doThing(new Two());

即使运行时的实际对象是Two对象而不是One对象,也是如此 选择哪个重载方法调用(换句话说,签名的 方法)不是在运行时动态决定的。请记住,参考 type(不是对象类型)确定调用哪个重载方法!

当您使用两个对象参数调用doThing()方法时,您将调用一个超类doThing()方法.doThing()方法需要一个One对象和两个IS-A One。  因此,在这种情况下,编译器扩展了对One对象的两个引用,并且 调用成功。这里的关键点是参考扩展取决于 继承,换句话说是IS-A测试。

答案 2 :(得分:1)

优秀的SCJP for Java 6声明:

  

如果方法被覆盖但是你使用了多态(超类型)   引用用重写方法引用子类型对象,   编译器假设你正在调用的超类型版本   方法

所以基本上使用supertype作为参考,你告诉编译器使用超类型方法。

答案 3 :(得分:0)

这是一个棘手的问题 你的声明
One o = t;
我想,你假设一级'o'等于二级't',它实际上不等于二级't' 因为Class Two't'是继承自Class One,所以它将在你的情况下分配基类One,
因此变量't'是类One的引用,因此将调用类One的方法。 更多的是你创建了一个名为ClassC类的类,并尝试设置你的语句
ClassC c= new ClassC ()
然后
One o = c;
您将收到错误...希望您的问题得到答案。

答案 4 :(得分:-1)

在编译时,编译器在类One中搜索方法doThing(Two t),但由于没有具有该签名的方法,因此它开始扩展其搜索并找到doThing(One o)。然后它保存带有描述符one parameter whose type is One : void的二进制文件。在运行时,因为调用该方法的对象的类型为Two,所以在类Two中,它会查找与描述符匹配的方法,而不会搜索接受对象的方法doThing Two,因为它考虑二进制文件中的描述符,它将调用链接到方法doThing(One o)

java规范对此有很大帮助。 here是链接