2017-10-28 259 views
-1

动态绑定和构造函数链之间的困惑按照书上的我下面,下面的代码打印:在Java

public class DynamicBindingDemo { 
    public static void main(String[] args) { 

    m(new graduateStudent()); 
    m(new Student()); 
    m(new Person()); 
    m(new Object()); 
} 

    public static void m(Object x) { 
    System.out.println(x.toString()); 
    } 
} 

    class GraduateStudent extends Student { 
    } 

    class Student extends Person { 
     public String toString() { 
     return "Student"; 
    } 
} 

    class Person extends Object { 
    public String toString() { 
    return "Person"; 
    } 
} 

打印:

学生

学生

[email protected]

有人可以帮我解释为什么吗?在这里,我如何跟踪代码:

因此,m(new graduateStudent())调用m(Object x)的多态调用时,x.toString()由GraduateStuent类而不是Object类调用,因为GraduateStuent是实际对象的类型。在可以在GraduateStudent类中调用x.toString()之前,编译器会在GS类中隐式创建一个无参数构造函数,因为没有它。但是,在调用此构造函数之前,首先会调用学生类构造函数,因为它是超类。学生构造函数是在学生类中创建的(因为它没有),但是在构造函数被调用之前,人类构造函数被调用,因为它是超类等等直到我们到达Object超类,并且它的字符串方法应该被调用。 ...

我很确定我在很多事情上是错的(我是一个2个月的大学新生,这是一个小课程)。那么有人可以解释我出错了吗?

+0

方法重载你似乎完全混为一谈构造和动态绑定的想法。当你调用'toString()'(这是不必要的,顺便说一下,因为'println(Object)'会为你做),构造函数就完成了。您可以完全消除问题其余部分对构造函数的讨论。看看这是否足够简化它是有道理的。 – chrylis

回答

0

调用哪个方法不依赖于构造函数的执行。 然而,有一个技巧,父的构造函数作为子构造函数的第一步执行。它将被编译器添加,除非明确添加。例如。学生的构造函数如下所示:

public Student() { 
    super(); //parent initialised before child 
} 

实际上你做的是重写方法。

您可以考虑覆盖任何父类中的方法。 另外要了解这一点,你可以想到继承链: 毕业生 - >学生 - >人 - >对象

在链中找到的第一个toString方法将被调用。实际上这个版本用于原型继承,在java中它的实现方式不同。但是为了理解它应该是足够的。

所以对于你例子:

  • 你是不是覆盖父Student类的父类的方法使学生的方法被称为
  • 学生覆盖人toString方法,学生的方法被称为
  • 人覆盖对象的toString方法,人的方法被称为
  • 对象的toString被调用,因为它没有父类,并且包含方法toString。

你可以阅读更多有关在互联网:)