【问题标题】:Confused with Constructors and Subclasses对构造函数和子类感到困惑
【发布时间】:2014-02-27 05:57:07
【问题描述】:

我无法理解将构造函数与子类一起使用的概念。

这里是父类:

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类的构造函数传入了一个字符串参数,不应该只是打印出s吗?换句话说,输出不应该是:

B的构造函数被调用

在此先感谢,非常感谢你们提供的任何帮助。

【问题讨论】:

    标签: java class constructor subclass


    【解决方案1】:

    来自docs

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

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

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

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

    【讨论】:

      【解决方案2】:

      编译后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 的调用必须是构造函数中的第一条语句

      所以如果你显式调用超类构造函数,那么你必须在构造函数的开头调用,这应该是第一个语句。

      【讨论】:

        【解决方案3】:

        这样做的原因是,如果 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!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-14
          • 2021-06-12
          • 1970-01-01
          • 2021-12-31
          相关资源
          最近更新 更多