[英]Why does the program print the height value 0 instead of the one I set?
我很困惑在運行時如何調用方法和構造函數,因為派生的構造函數被打印3次並且打印高度為0
我已經嘗試在方法和構造函數中打印一些消息,以了解究竟發生了什么
public class Derived extends Base{
public static void main(String args[]){
System.out.println("Hello World");
Derived d = new Derived();
}
protected Derived(){
System.out.println("Inside Derived Const");
showAll();
}
protected void showAll(){
System.out.println("Inside Derived showAll");
System.out.println(getClass().getName()+" : "+height);
}
double height = 106.0;
}
class Base{
protected Base(){
System.out.println("Inside Base Const");
showAll();
}
protected void showAll(){
System.out.println("Inside Base showAll");
System.out.println(getClass().getName()+" : "+height);
}
double height = 196.0;
}
我期待輸出
Hello world
Derived : 106
Base : 196
相反,我得到了
Hello World
Inside Base Const
Inside Derived showAll
Derived : 0.0
Inside Derived Const
Inside Derived showAll
Derived : 106.0
這是因為您從Base
類Derived
類並隱藏變量並覆蓋方法。
每當您使用以下方法實例化Derived類時,您都在調用Base類的構造函數:
Derived d = new Derived();
這里當你調用上面的代碼時會發生什么:
Base()
構造函數, "Inside Base Const"
, showAll()
未被調用,因為它正在被覆蓋。 替代地調用Derived
類中的方法showAll()
, "Inside Base showAll"
, "Derived : 106.0"
,因為double height = 196.0;
inside Base類被double height = 106.0;
陰影double height = 106.0;
在Derived
類中。 需要注意的一點是,在創建子類對象時,不會創建超類對象的單獨對象。
僅創建具有超類變量的子類對象。
所以我們無法盲目地說每當執行一個類構造函數時,就會創建該類的對象。 請參考以下更改並查看。
public class Derived extends Base {
public static void main(String args[]) {
System.out.println("Hello World");
Derived d = new Derived();
d.getClass();
}
protected Derived() {
System.out.println("Inside Derived Const");
System.out.println("Sub class object hashcode :" + this.hashCode());
System.out.println(this.getClass().getName());
showAll();
}
protected void showAll() {
System.out.println("Inside Derived showAll");
System.out.println("Sub class object hashcode :" + this.hashCode());
System.out.println(getClass().getName() + " : " + height);
}
double height = 106.0;
}
class Base {
protected Base() {
System.out.println("Inside Base Const");
System.out.println("Super class object hashcode :" + this.hashCode());
System.out.println(this.getClass().getName());
showAll();
}
protected void showAll() {
System.out.println("Inside Base showAll");
System.out.println("Sub class object hashcode :" + this.hashCode());
System.out.println(getClass().getName() + " : " + height);
}
double height = 196.0;
}
產量
Hello World
Inside Base Const
Super class object hashcode :1917513796
Derived
Inside Derived showAll
Sub class object hashcode :1917513796
Derived : 0.0
Inside Derived Const
Sub class object hashcode :1917513796
Derived
Inside Derived showAll
Sub class object hashcode :1917513796
Derived : 106.0
我們可以看到,超類(Base)對象哈希碼和子類(Derived)對象哈希碼都是相同的,因此只創建了一個對象。
這個對象屬於Derived類,當我們嘗試打印創建對象的類的名稱時,它是打印子類的“Derived”。
當您第一次在超類中調用showAll()時,由於showAll已被覆蓋的方法,它沒有高度變量的值。但是在它調用的那一行沒有賦值。
當showAll()方法在子類內部調用時,它具有指定的值196.0。 這是由於隱藏變量*。
( 變量隱藏:當子類和父類都具有相同名稱的變量時,子類'變量隱藏父類'變量。)
你偶然發現java(以及其他面向對象語言)的工作存在嚴重缺陷。編譯器允許這種缺陷,但任何體面的IDE都會檢測到它並向你顯示警告,所以你發布這個問題告訴我你正在編譯而沒有啟用一些非常重要的警告。 在IDE上啟用盡可能多的警告,IDE將向您指出問題。 但我現在還要解釋一下。
在基類的構造函數中,您正在調用showAll()
。 這是一個非final方法,因此任何派生類都可以覆蓋它。
從構造函數中調用可覆蓋的方法是一個嚴重的錯誤 。
您可以看到,在調用基類構造函數時,尚未調用派生類構造函數,並且該對象尚未完全初始化。 所以,簡單發生的是,在你的基類構造函數運行的那一刻,你的語句double height = 106.0;
您的派生類尚未執行。 這就是派生類的height
成員似乎包含零的原因。 零只是默認值, 106.0
尚未存儲在其中。
如果在IDE中啟用了正確的警告,那么IDE將在構造函數中警告您有關非最終方法的任何調用。 (在我看來,這不應該是一個警告,它應該是一個錯誤。)
那么,讓我簡要介紹一下您的期望與結果:
您期望以下內容:
Hello world
Derived : 106
Base : 196
那是錯的。 如果您沒有其他錯誤,您應該預期以下內容:
Hello world
Base : 196
Derived : 106
這是因為您的Derived
構造函數以對Base
構造函數的隱式(隱藏)調用開始,因此將始終首先調用基礎構造函數。 您的System.out.println("Inside X Const")
語句就是明證。
但相反,你得到以下內容:
Hello World
Derived : 0.0
Derived : 106.0
這兩行看起來都來自'Derived'類,因為getClass()
將返回當前對象的類,並且您只創建了一個對象,它是Derived
一個實例。 因此,當從Derived
類中調用時, getClass()
將返回Derived
,並且當從Base
類中調用時,它也將返回Derived
。
然后我已經解釋過的0.0
來自Derived
實例的未初始化的成員變量,因為你從基類的構造函數中調用showAll()
可showAll()
,所以派生類沒有機會初始化自己在調用該方法的那一刻。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.