2012-02-21 195 views
3

给定一个随机类:子类构造函数 - 为什么必须为子类构造函数存在默认构造函数?

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都必须一有空的构造?我会假定它会使用类似的构造函数而不是默认的构造函数。我尝试编译没有默认的构造函数,但我得到没有它的以下消息...

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

任何人都可以解释这是为什么?

回答

9

重要的一点是要明白,任何构造函数的第一行是调用超级构造函数。如果你不自己调用一个超级构造函数,编译器会使你的代码变得简短一些,在底部插入super()

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

你有一个情况下,你不必在你的B-构造一个super(...),所以编译器插入super()调用本身,但你有A-构造函数参数,以便在默认A() - 构造函数没有插入,你必须手动提供A() - 构造函数,或者调用A(i)构造函数。在这种情况下,我建议只是有

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

这是正确的说,当一个对象被实例化时,它所继承的所有对象也被实例化(如构建块)? – Zak 2012-02-21 01:20:04

+0

我宁愿说当你实例化一个对象时,构造函数负责初始化对象。如果你继承它,那么子类的构造函数负责初始化添加的部分,而超级构造函数负责剩下的部分。这一直递归地应用于Object类本身。 – 2012-02-21 01:27:56

6

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

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

如果你不这样做,编译器会尝试实例A本身,通过调用它的默认构造函数。

2

如果不拨打电话,使用super(i)为您的构造函数的第一行超级构造函数就会隐式调用默认的构造函数的超级

相关问题