在Java中,重寫指的是子類寫一個和父類同名、參數列表相同、返回值類型也相同的方法。但是,在編譯時和運行時,重寫會有不同的影響。
在編譯期,編譯器會檢查你的重寫方法是否符合重寫的規則(即同名、參數列表相同、返回值類型也相同),如果符合,那么就會編譯通過。如果不符合,則會提示編譯錯誤。
public class SuperClass {
public void foo() {}
}
public class SubClass extends SuperClass {
// 編譯錯誤
public void foo(int a) {}
}
上面的代碼中,子類重寫了父類的foo方法,并且將參數列表修改為了int。這樣是不符合重寫規則的,編譯器會提示“SubClass中的foo(int)無法覆蓋SuperClass中的foo();返回類型不同”,即“返回類型不同”這個錯誤。
在運行期,重寫方法的調用是根據對象的實際類型來確定的,而不是根據變量的聲明類型。也就是說,如果一個對象是父類的實例,但是它的實際類型是子類,那么調用重寫方法的時候,就會調用子類的這個方法。
SuperClass obj = new SubClass();
obj.foo();
上面的代碼中,雖然obj的聲明類型是SuperClass,但是obj的實際類型是SubClass,因此調用obj的foo方法時,實際上調用的是SubClass的foo方法。
需要注意的是,如果重寫方法的返回值類型是一個基本類型或者void,那么子類中的返回值類型必須和父類中的返回值類型完全相同。如果重寫方法的返回值類型是一個引用類型(比如Object),那么子類中的返回值類型必須是父類中返回值類型的子類。
public class SuperClass {
public Object foo() { return new Object(); }
}
public class SubClass extends SuperClass {
// 編譯錯誤
public String foo() {}
}
上面的代碼中,子類重寫了父類的foo方法,并且將返回值類型修改為了String。這樣是不符合重寫規則的,編譯器會提示“SubClass中的foo()無法覆蓋SuperClass中的foo();不兼容的返回類型:Object無法轉換為String”,即“不兼容的返回類型”這個錯誤。