簡體   English   中英

Java子類構造函數不調用父類構造函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM