前几天我遇到了一个奇怪的情况。这是:
我有一个抽象类和一个扩展它的子类。抽象类有一个无参数构造函数来初始化映射,但仅此而已。
子类没有我显式编写的任何构造函数,并且一切正常。
然后有一天,我在子类中添加了一个自定义构造函数,其中包含一堆用于单元测试的参数。然而,这破坏了我的主程序,因为其父类中的映射始终为空。
为了解决这个问题,我在子类中放置了另一个完全空白的构造函数(没有参数或任何东西)。由于某种原因,这确保了父类(super class)构造函数将被调用并且不会抛出空指针异常。为什么以前没有被调用,为什么现在可以工作?
子类:
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<>();
}
最佳答案
我无法解释为什么您会遇到带有 attributes=null
的 BillToSite
实例。这与 Java 的工作方式相矛盾。但我可以解释为什么你必须编写无参数构造函数。
显式无参数构造函数的必要性
我认为在您的程序中 BillToSite
实例是使用 new BillToSite()
创建的,无论是显式的还是通过某个框架...(否则该类不会有任何情况)。
在原始的 BillToSite.java
中,您没有显式构造函数,因此 Java 编译器为您创建了一个与您询问的构造函数实际上相同的构造函数。
引入 6-args 构造函数会停用编译器自动创建无参数构造函数的功能,并且由于您的代码依赖于此构造函数,所以我很清楚它无法再工作。通常,您应该在 new BillToSite()
调用中遇到编译错误。如果您没有得到它们,我猜实例创建是使用反射发生在某个隐藏的地方。
因此,当您编写显式无参数构造函数时,您重新引入了不再自动生成的缺失元素。
调用 super 构造函数
你永远不需要用 super()
显式地开始一个构造函数(如果你省略它,我们可能会认为它是不好的风格,因此不清楚要使用哪个父类(super class)构造函数)。如果您没有显式调用 super(...)
或 this(...)
构造函数,编译器会有效地插入 super()
> 从一开始。在这方面,其他一些答案具有误导性。
因此,将该行添加到 BillToSite(...)
构造函数中不会改变任何内容。
我建议您在调试器控制下运行程序,并在 BillToSite()
构造函数上设置断点,并观察 attributes
字段。我确信它将被初始化为一个空的HashSet
。如果您稍后遇到空值,则问题一定出在代码的另一部分。
关于Java子类构造函数不调用父类构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46307275/