前几天我遇到了一个奇怪的情况。这是:
我有一个抽象类和一个扩展它的子类。抽象类有一个无参数构造函数来初始化一个地图,但就是这样。
子类没有我明确写的任何构造函数,一切正常。
然后有一天,我在子类中添加了一个自定义构造函数,其中包含一组用于单元测试的参数。然而,这打破了我的主程序,因为其父类中的映射始终为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<>();
}
答案 0 :(得分:3)
我无法解释为什么您使用BillToSite
体验attributes=null
个实例。这与Java的工作方式相矛盾。但我可以解释为什么你必须编写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()
来初始化映射。