Java子类构造函数不调用父类构造函数

时间:2017-09-19 18:17:13

标签: java inheritance constructor

前几天我遇到了一个奇怪的情况。这是:

我有一个抽象类和一个扩展它的子类。抽象类有一个无参数构造函数来初始化一个地图,但就是这样。

子类没有我明确写的任何构造函数,一切正常。

然后有一天,我在子类中添加了一个自定义构造函数,其中包含一组用于单元测试的参数。然而,这打破了我的主程序,因为其父类中的映射始终为null。

为了解决它,我在子类中放置了另一个完全空白的构造函数(没有参数或任何东西)。这由于某种原因确保将调用超类构造函数并且不抛出空指针异常。为什么之前没有被调用,为什么它现在正在运行?

子类:

public class BillToSite extends XWStoreRequestDataElement {
private String country;
private String state;
private String county;
private String city;
private String zip;
private String address;

public BillToSite() { } //WHY DOES THIS FIX IT???

//Only used for unit test. 
public BillToSite(String address, String city, String state, String zip, String county, String country){
    this.address = address;
    this.city = city;
    this.state = state;
    this.zip = zip;
    this.county = county;
    this.country = country;
}

抽象类:

public abstract class XWStoreRequestDataElement {
private Map<String, String> attributes;

public XWStoreRequestDataElement(){
    attributes = new HashMap<>();
}

3 个答案:

答案 0 :(得分:3)

我无法解释为什么您使用BillToSite体验attributes=null个实例。这与Java的工作方式相矛盾。但我可以解释为什么你必须编写no-args构造函数。

显式no-args构造函数的必要性

我认为在您的程序中BillToSite实例是使用new BillToSite()创建的,显式或某些框架...(否则该类将没有任何实例)。

在原始BillToSite.java中,您没有明确的构造函数,因此Java编译器为您创建了一个,实际上与您询问的相同。

介绍6-args构造函数会停用编译器自动创建no-args构造函数,并且由于您的代码依赖于此构造函数,因此我很清楚它不能再工作了。通常,您应该有new BillToSite()次调用的编译错误。如果你没有得到它们,我猜想实例创建发生在一些隐藏的地方使用反射。

所以,当你编写显式的no-args构造函数时,你重新引入了不再自动生成的缺失元素。

调用超级构造函数

您永远不需要使用super()显式地开始构造函数(如果省略它,我们可能会认为它是错误的样式,因此不清楚要使用哪个超类构造函数)。如果您没有显式调用super(...)this(...)构造函数,编译器会在最开始时有效地插入super()。在这方面,其他一些答案具有误导性。

因此,将该行添加到BillToSite(...)构造函数中无法改变任何内容。

我建议您使用BillToSite()构造函数上的断点在调试器控件下运行程序,并观察attributes字段。我确定它会被初始化为空HashSet。如果您以后遇到空值,则问题必须出现在代码的另一部分中。

答案 1 :(得分:0)

只需拨打super();中的public BillToSite(){}即可 例如:

public BillToSite(String address, String city, String state, String zip, String county, String country){
    super();
    this.address = address;
    this.city = city;
    this.state = state;
    this.zip = zip;
    this.county = county;
    this.country = country;
}

答案 2 :(得分:0)

默认情况下,Java提供了一个no-args构造函数,可以为任何没有任何显式定义的构造函数的类调用super()。但是,当您明确定义构造函数时,Java不会这样做,因此您必须自己调用super()

所以,当你没有那个子类构造函数时,Java为你处理了no-args构造函数,但是当你添加了那个子类构造函数时,Java就停止了处理,所以你必须自己做。另一个解决方案是在原始子类构造函数中显式调用super()而不是为它设置单独的no-args构造函数,因为您真正需要做的就是调用super()来初始化映射。