13

我一直认为构造函数不是继承的,但是看看这段代码:

class Parent {
    Parent() {
        System.out.println("S1");
    }
}

class Child extends Parent {
    Child() {
        System.out.println("S2");
    }
}

public class Test5 {
    public static void main(String[] args) {
        Child child = new Child();
    }
}

//RESULT:
//S1
//S2

它表明 Child 继承了构造函数。为什么结果上有 S1?是否有可能创建 2 个没有参数的构造函数,并且在没有基本构造函数的结果上只有子构造函数(只有 S2)?

4

7 回答 7

27

无论您在这里看到什么,都称为构造函数链接。现在什么是构造函数链:

构造函数链接通过使用继承发生。子类构造方法的首要任务是调用其超类的构造方法。这确保了子类对象的创建从继承链中它上面的类的初始化开始。

继承链中可以有任意数量的类。每个构造函数方法都会调用链,直到到达并初始化顶部的类。然后,随着链回到原始子类,初始化下面的每个后续类。这个过程称为构造函数链接。(来源

这就是你的程序中发生的事情。当你编译你的程序时,你Child的编译方式是这样的javac

class Child extends Parent 
{ 
  Child()
  {
    super();//automatically inserted here in .class file of Child
    System.out.println("S2");
  }
}

并且您的 Parent 类转换为以下内容:

Parent() 
{
    super();//Constructor of Object class
    System.out.println("S1");
}

这就是为什么您的输出显示为:

S1 //output from constructor of super class Parent
S2 //output from constructor of child Class Child
于 2013-03-30T18:19:55.787 回答
13

Java 文档说:

子类从其超类继承所有成员(字段、方法和嵌套类)。构造函数不是成员,所以子类不能继承,但是子类可以调用超类的构造函数。

如果您不声明任何类型的构造函数,则会添加默认值。

如果您没有在子类的第一行调用任何其他构造函数,则会调用 super()。

于 2013-03-30T18:17:04.423 回答
3

你写:

它表明 Child 继承了构造函数。

构造函数不能被继承。类可以被继承,所以 Child 不继承任何构造函数。Child继承类Parent。Parent 继承类 Object。当您调用 Child 构造函数时,在运行 Child 构造函数的代码之前,会自动调用 Object 构造函数,然后调用 Parent 构造函数。

这就是为什么你会得到这个结果:

S1
S2
于 2013-03-30T18:17:56.157 回答
1

构造函数不被继承。

超类构造函数不会在派生类中继承。

是否有可能创建 2 个没有参数的构造函数,并且在没有基本构造函数的结果上只有子构造函数。

不,它不可能在 Java 中每个派生类构造函数都调用超类构造函数。如果不添加它,则调用无参数构造函数。

public SuperClass() {
   ...
}

public DerivedClass() {
  //Compiler here call no argument constructor of Super class.
}
于 2013-03-30T18:17:11.413 回答
0

除非已定义显式构造函数,否则构造函数将始终调用其超类构造函数。来自Java 语言规范

如果构造函数体不是以显式构造函数调用开始,并且被声明的构造函数不是原始类 Object 的一部分,则构造函数体隐式地以超类构造函数调用“super();”开始,对构造函数的调用它的直接超类不带参数。

于 2013-03-30T19:43:13.233 回答
0
public class HelloWorld{

    private static class A {
        A(String x) {
            System.out.println(x);
        }
    }
    
    private static class B extends A {
        
    }

    public static void main(String []args){
        B b =  new B();
        System.out.println("Hello World");
    }
}

输出:

/*
error: constructor A in class A cannot be applied to given types;
    private static class B extends A {
                   ^
  required: String
  found: no arguments
  reason: actual and formal argument lists differ in length
1 error
*/

所以这意味着构造函数永远不会被继承

因此,这里发生的是B 类的无参数构造函数尝试调用A 类的无参数构造函数,但它没有发现因此给出错误。

如果我们在类 A中添加参数少的构造函数,那么这个程序将正常工作。

于 2020-09-23T06:11:23.473 回答
0

如果超类没有默认构造函数,那么子类也需要定义显式构造函数。否则会抛出编译时异常。在子类构造函数中,在这种情况下必须调用超类构造函数,它应该是子类构造函数中的第一条语句。

于 2019-04-05T06:34:22.707 回答