**Java 代碼-MySuper 類是父類,由 MySub 類擴展。我正在創建物件 MySub mySub = new MySub()。我以為輸出會是“y”,但是當我嘗試運行代碼時它是顯示null作為輸出 **
class MySuper {
String strl = "x";
public MySuper() {
myMethod();
}
void myMethod() {
System.out.print(strl);
}
}
class MySub extends MySuper {
String str2 = "y";
void myMethod() {
System.out.print(str2);
}
public static void main(String[] args) {
MySub mySub = new MySub();
}
}
uj5u.com熱心網友回復:
使用的隱式建構式MySub如下所示:
class MySub extends MySuper {
String str2;
MySub() {
super();
str2 = "y";
}
// rest omitted for brevity
}
欄位初始化被“折疊到”建構式中。但是首先呼叫超級建構式。因此,當超級建構式呼叫myMethod()被子類覆寫的方法時,該str2欄位尚未被分配非默認值。這會導致您的代碼列印出來null。
這就是為什么你應該避免在建構式中呼叫可覆寫的方法。
uj5u.com熱心網友回復:
這是由于 Java 動態方法分派。
在你的例子中。當您使用默認建構式實體化一個MySub實體時,這會隱式執行對超類的建構式的呼叫。在超類的建構式中有一個呼叫,myMethod()它在 中宣告MySuper并被覆寫MySub。
現在,即使myMethod是從超類的建構式中呼叫的,這可能會讓我們誤以為myMethod正在呼叫超類的版本,但這并不是實際發生的情況。
執行所有這些呼叫的實體仍然是一個MySub實體;因此myMethod,Java 呼叫的實作是最接近 的實作MySub,即被myMethod覆寫MySub。
那么,如果在這種情況下,myMethod在超類的建構式中呼叫的版本是被 覆寫的版本MySub,為什么它不列印str2值?這是因為,雖然方法呼叫是動態分派的,但欄位是靜態分派的。在 Java 中,只有方法可以覆寫其基類的方法。子類的欄位只能隱藏基類的欄位(同名)。因此 Java 在編譯時已經知道哪些欄位正在被使用,并且只有在運行時才知道正在呼叫哪些方法實作。這意味著當您在子類中使用欄位時,您可以確定您使用的欄位始終是您所參考的欄位。
回到你的例子,因為myMethod是從超類的建構式呼叫的,此時我們仍在初始化父物件,子類的欄位還沒有初始化,它們仍然包含它們的默認值(默認值參考為空)。因此,在您的動態調度myMethod中,我們正在列印靜態調度的值,該值str2仍為 null,因為子類初始化尚未發生。
uj5u.com熱心網友回復:
小錯誤:
- null輸出是因為擴展了MySuper類并且不需要擴展MySuper類,因為可以在包中的任何位置創建默認類物件而無需擴展它。
- 在創建物件mySub之后,您還沒有呼叫方法myMethod()。這就是它沒有將輸出列印為y的原因。
解決方案:嘗試下面的代碼,它運行順利。
class MySuper {
String strl = "x";
public MySuper() {
myMethod();
}
void myMethod() {
System.out.print(strl);
}
}
// class MySub extends MySuper {
class MySub {
String str2 = "y";
void myMethod() {
System.out.print(str2);
}
public static void main(String[] args) {
MySub mySub = new MySub();
// extra line added
mySub.myMethod();
MySuper ms=new MySuper();
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/479277.html
