【问题标题】:Subclass constructors - Why must the default constructor exist for subclass constructors?子类构造函数 - 为什么子类构造函数必须存在默认构造函数?
【发布时间】:2012-02-21 00:35:53
【问题描述】:

给定一个随机类:

public class A<T> {
    public T t;

    public A () {}  // <-- why is this constructor necessary for B?
    public A (T t) {
        this.setT(t);
    }
    public T getT () {
        return this.t;
    }
    protected void setT (T t) {
        this.t = t;
        return;
    }
}

还有一个扩展类:

public class B extends A<Integer> {
    public B (Integer i) {
        this.setT(i);
    }
}

为什么 B 要求 A 有空的构造函数?我会假设它会想要使用类似的构造函数而不是默认构造函数。我尝试在没有默认构造函数的情况下进行编译,但没有它我收到以下消息...

java.lang.NoSuchMethodError: A: method <init>()V not found at B.<init>

谁能解释这是为什么?

【问题讨论】:

    标签: java constructor subclass


    【解决方案1】:

    重要的是要理解任何构造函数的第一行都是调用超级构造函数。如果您自己不调用超级构造函数,编译器会通过在幕后插入super() 来缩短您的代码。

    此外,如果您没有 任何 个构造函数,则会自动插入一个空的默认构造函数 - 这里是 A()B()

    您的 B 构造函数中没有 super(...),因此编译器会自行插入 super() 调用,但您确实有一个带参数的 A 构造函数所以默认的 A()-constructor 没有被插入,你必须手动提供 A()-constructor,或者调用 A(i)-constructor。在这种情况下,我建议只使用

    public class B extends A<Integer> {
        public B (Integer i) {
            super(i);
        }
    }
    

    【讨论】:

    • 当一个对象被实例化时,它所继承的所有对象也被实例化(就像积木一样)是否正确?
    • 我宁愿说,当你实例化一个对象时,构造函数负责初始化该对象。如果您对其进行子类化,则子类化构造函数负责初始化添加的部分,而超级构造函数负责其余部分。这一直递归地应用到 Object 类本身。
    【解决方案2】:

    你可以在A中使用你自己的构造函数,但是你必须从B的构造函数中显式调用它,例如:

    public B(Integer i) {
      super(i);
      ...
    }
    

    如果您不这样做,编译器将尝试通过调用其默认构造函数来实例化A 本身。

    【讨论】:

      【解决方案3】:

      如果您不使用 super(i) 作为构造函数的第一行来调用超级构造函数,它将隐式调用默认的超级构造函数

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-13
        • 1970-01-01
        • 2011-06-26
        相关资源
        最近更新 更多