[英]Java subclass constructors not calling parent class 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<>();
}
我無法解釋為什么您會遇到帶有attributes=null
BillToSite
實例。 這與Java的工作方式相矛盾。 但是我可以解釋為什么您必須編寫no-args構造函數。
我想在您的程序中BillToSite
實例是使用new BillToSite()
顯式地或通過某些框架創建的(否則該類將沒有任何實例)。
在原始的BillToSite.java
您沒有顯式的構造函數,因此Java編譯器為您創建了一個構造函數,實際上與您所要求的構造函數相同。
引入6-args構造函數會停用編譯器對no-args構造函數的自動創建,並且由於您的代碼依賴於此構造函數,因此對我來說很明顯它再也無法工作了。 通常,對於new BillToSite()
調用,您應該會遇到編譯錯誤。 如果您沒有得到它們,我猜想實例創建是使用反射在某個隱藏的地方進行的。
因此,當您編寫顯式的無參數構造函數時,您重新引入了不再自動生成的丟失元素。
您永遠不需要用super()
顯式地開始構造函數super()
如果您省略它,我們可能會認為它是不好的樣式,因此不會弄清楚要使用哪個超類構造函數)。 如果您未顯式調用super(...)
或this(...)
構造函數,則編譯器將在最開始有效地插入super()
。 在這方面,其他一些答案是誤導的。
因此,將該行添加到BillToSite(...)
構造函數中無法更改任何內容。
我建議您在調試器控制下,在BillToSite()
構造函數上使用一個斷點來運行程序,並注意attributes
字段。 我確定它將初始化為一個空HashSet
。 如果您以后遇到空值,則問題必須出在代碼的另一部分。
只需調用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;
}
默認情況下,Java提供了一個no-args構造函數,該構造函數為沒有任何顯式定義的構造函數的任何類調用super()
。 但是,當您顯式定義構造函數時,Java不會這樣做,因此您必須自己調用super()
。
因此,當您沒有該子類構造函數時,Java會為您處理no-args構造函數,但是當您添加該子類構造函數時,Java會停止處理它,因此您必須自己做。 另一種解決方案是只在原始子類構造函數中顯式調用super()
,而不要為其使用單獨的no-args構造函數,因為您真正需要做的就是調用super()
來初始化地圖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.