与构造函数和子类混淆

时间:2014-02-27 05:57:07

标签: java class constructor subclass

我无法理解使用带子类的构造函数的概念。

这是父类:

public class A
{
    public A()
    {
        System.out.println("The default constructor of A is invoked");
    }
}

儿童班:

public class B extends A
{
    public B(String s)
    {
        System.out.println(s);
    }
}

我的主要方法:

public class C
{
    public static void main (String[] args)
    {
        B b = new B("The constructor of B is invoked");
    }
}

当我运行C时,我得到的输出是

  

调用A的默认构造函数

     

调用B的构造函数

我不明白为什么来自A类的信息正在输出。因为你将一个字符串参数传递给B类的构造函数,所以它不应该打印出来吗?换句话说,输出不应该只是:

  

调用B的构造函数

在此先感谢,我非常感谢你们给予的任何帮助。

3 个答案:

答案 0 :(得分:7)

来自docs

  

如果构造函数没有显式调用超类构造函数,Java编译器会自动插入对超类的无参数构造函数的调用。如果超类没有无参数构造函数,则会出现编译时错误。对象确实有这样的构造函数,因此如果Object是唯一的超类,则没有问题。

因此,即使您没有显式调用超类构造函数,编译器也会在类super()的构造函数中插入一个名为B的语句。

这就是B类构造函数在编译后的样子。

public B(String s){
    super(); // this is inserted by the compiler, if you hadn't done it yourself.
    System.out.println(s);
}

答案 1 :(得分:4)

编译后class B -

public class B extends A{
    public B(String s){
        super();
        System.out.println(s);
    }
}

为什么!逻辑答案是孩子不能在没有父母的情况下存在,所以父母被快速初始化,然后是孩子。

从技术上讲 - 如果你没有显式调用super class,那么构造函数编译器会为你做。在你的案件中究竟发生了什么。

如果你明确地调用超类构造函数可以帮助你更仔细地理解它,那么这是一个很好的实验 -

public class B extends A{
    public B(String s){
        System.out.println(s);
        super(); // invoking super later
    }
}

您收到编译错误 -

  

错误:调用super必须是构造函数中的第一个语句

因此,如果您显式调用超类构造函数,则必须在构造函数的开头调用,这应该是第一个语句。

答案 2 :(得分:0)

它这样做的原因是,如果B确实是A的子类,B需要包含A中的所有字段。因此,当您调用构造函数时 B b = new B("The constructor of B is invoked"); 它调用A的默认构造函数来初始化A的字段,因此B实际上是逻辑上的

public class B extends A
{
    public B(String s)
    {
        super();
        System.out.println(s);
    }
}

super只调用A的默认构造函数。如果编译器没有这样做,那么你将在B中继承未初始化的字段,因为它继承自A!