1. 程式人生 > >Java 覆寫和過載定義與區別 (面試題)

Java 覆寫和過載定義與區別 (面試題)

覆寫和過載

方法的覆蓋(Overriding)和過載(Overloading)是Java多型性的不同表現。覆蓋(也可以叫重寫,覆寫)是父類與子類之間多型性的一種表現,而過載是一個類中多型性的一種表現。

(一)覆寫:

1.方法的覆寫(****重點,Java核心)

定義:子類定義了與父類方法名稱,引數列表,返回值完全相同的方法。被覆寫的方法不能擁有比父類更為嚴格的訪問控制權限。

//Override.java
class A{
    public int getVal(){
        return 5;
    }
}
class B extends A{
    public int getVal(){
        return 10;
    }
}
public class Override{
    public static void main(String[] main){
        B b = new B();
        System.out.println(b.getVal());
    }
}
程式執行結果:10

對於B類的物件b,其getVal方法已經對A類的getVal方法進行了覆蓋,所以當B呼叫getVal方法時,程式執行其子類方法體內中的內容,返回結果為10.

class A{  //包訪問許可權
    public void fun(){
        System.out.println("我是爸爸");
    }
}
class B extends A{
    public void fun(){
        System.out.println("我是兒子");
    }
}
public class Override{
    public static void main(String[] args){
        B b = new B();
        A a = (A)b;				//把b強轉成A的型別:上面兩句等價於A a = new B();
	    per.fun();
    }
}
程式執行結果:我是兒子

上例中物件a時B類建立的一個物件,雖然被強制轉換成A類,但其仍然時B類的例項物件,B類重寫了A類的getVal的例項方法,因此b呼叫了其自身的方法。這種操作也叫做向上轉型

注意:

1.判斷呼叫的到底是父類方法還是子類方法

a.看new在哪(當前使用的物件是通過那個類new的)
b.呼叫的方法有沒有被子類覆寫,如果被覆寫,呼叫的一定是被覆寫後的方法。

2.訪問控制權限:

private < default(啥也不寫)—包訪問許可權(在同一個原始檔中的訪問許可權)< public

方法覆寫不能出現private關鍵字

3.覆蓋方法的呼叫原則:

  1. 父類日被覆蓋的方法的宣告必須要和子類的同名方法的宣告完全匹配,才能達到覆蓋的效果。
  2. 覆蓋方法的返回值必須和被覆蓋方法的返回值一致。
  3. 被覆蓋的方法不能為private,否則在其子類中只是新定義了一個方法,並沒有對其進行覆蓋,因為修飾符為private的方法,子類不能從父類繼承,所以就不存在覆蓋。
  4. 在Java程式執行時,系統根據呼叫該方法中的物件,來決定實際呼叫的是子類的方法還是父類的方法,對於一個子類的物件,如果該子類覆蓋了父類方法,則執行時系統呼叫的時子類的方法,否則呼叫的是父類的方法。
  5. 覆蓋後的方法不能比被覆蓋的方法有更加嚴格的訪問許可權(可以相同)。
  6. 覆蓋後的方法不能比覆蓋前的方法產生更多的例外,即丟擲更多異常。

下段程式碼體現了以上5,6兩點:

class{
		void f() throws IOException{   //f()為default型別,丟擲Exception。
		//方法體
		}
}
class B extends A{
		private void f() throws Exception{ 
		//錯誤1:private許可權小於default 
		//錯誤2:Exception異常比IOException異常範圍大,因為Exception包含IOException.
		}
}

2.屬性的覆寫(瞭解)

屬性的覆寫:子類和父類定義了屬性名稱完全一樣的屬性的時候,叫做屬性覆寫。

(二)過載

如果在一個類中定義了多個同名的方法,它們有不同的引數個數,不同的引數型別或不同的引數次序,則成為方法的過載。類的同一種功能有多種實現方式,具體採用哪種,取決於呼叫者給定的引數。例如雜技師訓練動物,對於不同的動物有不同的訓練方式。

public void train(Dog dog){
   //訓練小狗站立,排隊...
}
public void train(Monkey monkey){
  //訓練小猴敬禮,翻跟斗...
}

當該類的物件呼叫train方法時,如果方法引數時Dog就會呼叫訓練小狗的相關操作,如果方法引數時Monkey物件,就會呼叫訓練小猴的相關操作。
對於類的方法(包括從父類繼承的方法)。如果有兩個方法的方法名相同,但引數不一樣,這時候可以說一個方法是另一個方法的過載方法。
方法過載是指多個方法享有相同的名字,但是這些方法的引數必須不同,或者是引數個數或者引數型別不同。返回型別不能用來區分過載的方法。

方法過載規則:

  1. Java方法過載要求同名的方法必須有不同的引數表,僅有返回型別不同是不足以區分兩個過載方法的。
  2. 引數型別的區分度一定要足夠,即引數型別,個數,順序至少有一項不同。
  3. 方法的修飾符可以不同。
  4. 一個類的多個構造方法之間還可以互相呼叫,這個要通過關鍵字this來實現。

面試題:解釋方法過載與方法重寫的區別

a.概念上:

過載:方法名稱相同,引數列表不同,與返回值無關。
重寫:方法名稱,返回值,引數列表完全一樣,只是許可權不一樣,子類不能擁有比父類更為嚴格的許可權。

b.範圍:

過載發生在同一個類中,是內部多個方法之間的關係。重寫:子類與父類之間,才有方法覆寫。

c.許可權要求:

過載沒有許可權要求。覆寫:在有繼承關係的類之中,被覆寫的方法不能擁有比父類更嚴格的訪問控制權限
(用final修飾的方法是不能被子類覆蓋的,只能被過載)。