有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

结果:1

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)。如果有人解释一下,我会很高兴的

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

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

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


共 (5) 个答案

  1. # 1 楼答案

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

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

    因为签名不匹配,Two.doThing(Two)不会覆盖One.doThing(One),并且因为oOne类型,所以调用One.doThing()

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

    Basically, "@nachokk - You are Overloading, not Overriding"

    在第一个场景中

    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)被调用

  2. # 2 楼答案

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

    java规范非常有助于解释这一点here是链接

  3. # 3 楼答案

    这是一个棘手的问题
    你的立场
    One o = t;
    我想,你是在假设一级'o'等于二级't',这实际上并不等于二级't'
    由于类2“t”是从类1继承而来的,因此在您的情况下,它将分配基类1,
    所以变量't'是类1的引用,因此将调用类1的方法。
    再创建一个名为ClassC class的类,并尝试设置语句
    ClassC c= new ClassC ()
    然后
    One o = c;
    你会得到一个错误。。。希望你的问题能得到答案

  4. # 4 楼答案

    正如你所说,你只是超载了

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

    尽管运行时的实际对象是两个对象而不是一个对象,但 选择要调用的重载方法(换句话说,是 方法)在运行时不是动态决定的。记住,参考资料 类型(而不是对象类型)决定调用哪个重载方法

    当使用两个对象参数调用doThing()方法时,将调用一个超类doThing()方法。doThing()方法需要一个One对象,而Two IS-a-One。 因此,在本例中,编译器将两个引用扩展到一个对象 调用成功。这里的关键点是,参考加宽取决于 换句话说,继承是一种考验

  5. # 5 楼答案

    优秀的书籍SCJP for Java 6指出:

    If a method is overridden but you use a polymorphic (supertype) reference to refer to the subtype object with the overriding method, the compiler assumes you’re calling the supertype version of the method.

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