为什么声明子类对象时会调用父类的构造函数?

40

考虑以下代码:

class Test {
    Test() {
        System.out.println("In constructor of Superclass");
    }

    int adds(int n1, int n2) {
        return(n1+n2);
    }

    void print(int sum) {
        System.out.println("the sums are " + sum);
    }
}


class Test1 extends Test {
    Test1(int n1, int n2) {
        System.out.println("In constructor of Subclass");
        int sum = this.adds(n1,n2);
        this.print(sum);
    }

    public static void main(String[] args) {
        Test1 a=new Test1(13,12);
        Test c=new Test1(15,14);
    }
}

如果父类中有构造函数,那么每次我们为子类构造对象时都会调用它(例如,针对类Test1的对象a将调用Test1(int n1, int n2)以及其父类的Test()构造函数)。

为什么会这样呢?

此程序的输出结果为:

在超类构造函数中

在子类构造函数中

总和为25

在超类构造函数中

在子类构造函数中

总和为29

18个回答

1

在你的test1类中继承Test,这意味着你可以访问Test中的所有方法和变量。请注意,只有在为类分配了内存并且需要某个构造函数(默认或参数化)时,才能访问类的方法或变量。因此,当编译器发现它正在扩展一个类时,它将尝试找到超类构造函数,以便您可以访问其所有方法。


1

首先调用父类的构造函数,因为程序中所有的方法首先都存在堆中,在编译后它们存储到栈中,所以父类构造函数会被首先调用。


1
由于派生类继承了基类的属性,因此在一些情况下,派生类构造函数需要一些基类变量来初始化其变量。因此,它必须先初始化基类变量,然后再初始化派生类变量。这就是为什么Java首先调用基类构造函数,然后调用派生类构造函数的原因。
而且,在没有初始化父类的情况下初始化子类是没有意义的。

1
如果构造函数没有显式调用超类的构造函数,Java编译器会自动插入对超类无参构造函数的调用。如果超类没有无参构造函数,你将会得到一个编译时错误。Object类有这样的构造函数,因此如果Object是唯一的超类,就不会有问题。

答案没有说明原因?主要问题。 - Osama El-Ghonimy

1
我们知道类的成员变量(字段)在创建对象之前必须进行初始化,因为这些字段代表对象的状态。如果这些字段没有显式初始化,则编译器通过调用无参数默认构造函数隐式地提供它们的默认值。这就是为什么子类构造函数调用超类的无参数默认构造函数或者由编译器隐式调用。局部变量不会由编译器提供默认值。

1

我会从不同的角度来回答这个问题。

假设Java不会自动为您调用super构造函数。如果您继承了该类,您必须隐式地调用super构造函数或重新编写它。这将要求您具有对超类如何工作的内部知识,这是不好的。这也需要您重写代码,这也不好。

我同意在幕后调用super构造函数有点不直观。另一方面,我不确定他们如何以更直观的方式完成这项工作。


1
基类构造函数将在派生类构造函数之前被调用。这是有道理的,因为它保证了在执行派生类构造函数时基类已经被正确构造。这允许您在派生类的构造过程中使用一些来自基类的数据。

0

父类先存在! 就像现实世界中,孩子不能没有父母存在。 因此,在使用子类时,首先初始化父类(超类)非常重要。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接