![](/img/trans.png)
[英]How to call base class method with derived class Object when that method overridden in derived class?
[英]State of Derived class object when Base class constructor calls overridden method in Java
請參考下面的Java代碼:
class Base{
Base(){
System.out.println("Base Constructor");
method();
}
void method(){}
}
class Derived extends Base{
int var = 2;
Derived(){
System.out.println("Derived Constructor");
}
@Override
void method(){
System.out.println("var = "+var);
}
}
class Test2{
public static void main(String[] args) {
Derived b = new Derived();
}
}
看到的輸出是:
Base Constructor
var = 0
Derived Constructor
我認為var = 0的發生是因為Derived對象是半初始化的; 類似於Jon Skeet在這里所說的
我的問題是:
如果尚未創建Derived類對象,為什么會調用重寫的方法?
在什么時間點,var賦值為0?
是否存在需要此類行為的用例?
該Derived
對象被創建-它只是在構造函數尚未運行。 在創建它之后,對象的類型永遠不會在Java中更改,這在所有構造函數運行之前發生。
在構造函數運行之前, var
被賦予默認值0作為創建對象的過程的一部分。 基本上,類型引用被設置並且表示對象的其余內存被擦除為零(概念上,無論如何 - 它可能已經被擦除為零,作為垃圾收集的一部分)
這種行為至少會導致一致性,但這可能是一種痛苦。 就一致性而言,假設您有一個可變基類的只讀子類。 基類可能有一個isMutable()
屬性,該屬性實際默認為true - 但子類將其isMutable()
為始終返回false。 在子類構造函數運行之前,對象是可變的是奇怪的,但之后是不可變的。 另一方面,在您運行該類的構造函數之前最終在類中運行代碼的情況下,這絕對是奇怪的:(
一些指導原則:
盡量不要在構造函數中做太多工作。 避免這種情況的一種方法是在靜態方法中工作,然后使靜態方法的最后部分成為構造函數調用,它只是設置字段。 當然,這意味着當你正在做工作時,你不會從多態中獲益 - 但是在構造函數調用中這樣做無論如何都是危險的。
在構造函數期間盡量避免調用非final方法 - 這很可能會引起混淆。 記錄你必須 非常清楚的任何方法調用,以便任何覆蓋它們的人知道它們將在初始化完成之前被調用。
如果你必須在施工期間調用一個方法,那么通常不適合在之后調用它。 如果是這種情況,請記錄並嘗試在名稱中指明它。
盡量不要過度使用繼承 - 當你從一個非Object類以外的超類派生的子類時,這只會成為一個問題。繼承的設計是棘手的。
如果尚未創建Derived類對象,為什么會調用重寫的方法?
Derived
類構造函數隱式調用Base
類構造函數作為第一個語句。 Base
類構造函數調用method()
,它調用Derived
類中的重寫實現,因為這是正在創建其對象的類。 Derived
類中的method()
在該點看到var
為0。
在什么時間點,var賦值為0?
在調用Derived
類的構造函數之前,為var
賦予int
類型的默認值,即0。 它被分配值2隱含超構造器調用完成后並在聲明之前, Derived
類的構造函數開始執行。
是否存在需要此類行為的用例?
在非final
類的構造函數/初始化器中使用非final
非private
方法通常是一個壞主意。 原因在您的代碼中很明顯。 如果正在創建的對象是子類實例,則這些方法可能會產生意外結果。
請注意,這與C ++不同,在C ++中,類型在構造對象時確實發生了變化,因此從基類構造函數調用虛方法不會調用派生類的覆蓋。 同樣的事情在破壞期間反過來發生。 因此,對於來到Java的C ++程序員來說,這可能是一個小陷阱。
為了解釋這種行為,應該注意Java語言規范的一些屬性:
事件順序如下:
簡而言之,每當超類的構造函數調用非final方法時,我們都有進入此陷阱的潛在風險,因此不建議這樣做。 請注意,如果您堅持使用此模式,則沒有優雅的解決方案。 這里有兩個復雜且富有創意的,都需要線程同步(!):
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.