1. 程式人生 > >java中過載和覆蓋(又稱重寫)的區別

java中過載和覆蓋(又稱重寫)的區別

初次見到這兩個單詞並沒有什麼特別的感覺,但是時間長了,卻發現書上一會兒用override,一會兒又用overload,搞得我的迷迷糊。於是就做了個總結,希望能對和我一樣對這兩個概念模糊不清的網友有一個幫助。
override 可以翻譯為覆蓋,從字面就可以知道,它是覆蓋了一個方法並且對其重寫,以求達到不同的作用。對我們來說最熟悉的覆蓋就是對介面方法的實現,在介面中一般只是對方法進行了宣告,而我們在實現時,就需要實現介面宣告的所有方法。除了這個典型的用法以外,我們在繼承中也可能會在子類覆蓋父類中的方法。在覆蓋要注意以下的幾點:
1、覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配,才能達到覆蓋的效果;


2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
3、覆蓋的方法所丟擲的異常必須和被覆蓋方法的所丟擲的異常一致,或者是其子類;
4被覆蓋的方法不能為private,否則在其子類中只是新定義了一個方法,並沒有對其進行覆蓋。
overload對我們來說可能比較熟悉,可以翻譯為過載,它是指我們可以定義一些名稱相同的方法,通過定義不同的輸入引數來區分這些方法,然後再呼叫時,VM就會根據不同的引數樣式,來選擇合適的方法執行。在使用過載要注意以下的幾點:
1、在使用過載時只能通過不同的引數樣式。例如,不同的引數型別,不同的引數個數,不同的引數順序(當然,同一方法內的幾個引數型別必須不一樣,例如可以是fun(int, float), 但是不能為fun(int, int));
2、不能通過訪問許可權、返回型別、丟擲的異常進行過載

3、方法的異常型別和數目不會對過載造成影響;
4、對於繼承來說,如果某一方法在父類中是訪問許可權是priavte,那麼就不能在子類對其進行過載,如果定義的話,也只是定義了一個新方法,而不會達到過載的效果。
下面是對override和overload的測試程式,其中註釋中的內容都是會產生編譯錯誤的程式碼,我們將註釋去掉,看看在編譯時會產生什麼效果。
// 對overload測試的檔案:OverloadTest.java
public class OverloadTest {
// 下面幾個方法用來驗證可以通過定義不同的引數型別和引數的數目進行方法過載。
public void fun(){
System.out.println("method fun in OverloadTest, no parameter");
}

public void fun(float f) {
System.out.println("method fun in OverloadTest, parameter type: float");
}

public void fun(int i){
System.out.println("method fun in OverloadTest, parameter type: int");
}

public void fun(int i1, int i2) {
System.out.println("method fun in OverloadTest, parameter type: int, int");
}

// 下面的兩個方法用來驗證可以通過定義不同的引數順序進行方法過載。
// 需要注意:這裡的引數肯定不是相同的型別,否則的順序的先後就毫無意義。
public void fun1(int i, float f) {
System.out.println("method fun1 in OverloadTest, sequence of parameters is: int, float");
}

public void fun1(float f, int i) {
System.out.println("method fun1 in OverloadTest, sequence of parameters is: float, int");
}

// 下面的兩個方法用來驗證方法丟擲的異常對於過載的影響.
// 無論是異常的型別還是異常的個數都不會對過載造成任何的影響。
public void fun2() throws TestException {
System.out.println("fun2 in OverloadTest, exception: TestException");
}

public void fun2(int i) throws TestException, TestException1 {
System.out.println("fun2 in OverloadTest, exception: TestException, TestException1");
}

public void fun2(float f) throws Exception {
System.out.println("fun2 in OverloadTest, exception: Exception");
}

// 不能通過丟擲的異常型別來過載fun方法。
//public void fun(int i) throws Exception {
// System.out.println("method fun in OverloadTest, parameter type: int, exception: Exception");
//}

// 不能通過返回值過載fun方法。
//public boolean fun(int i) throws Exception {
// System.out.println("method fun in OverloadTest, parameter type: int, exception: Exception, return: boolean");
// return true;
//}

private void fun3() { }

// 不能通過不同的訪問許可權進行過載
public void fun3() { }

public static void main(String[] args) {
// 這裡只是定義了OverloadTest的例項,所以test不會呼叫
// OverloadTest1中的方法。
OverloadTest test = new OverloadTest1();
// 這裡定義了OverloadTest1的例項,因為OverloadTest1是OverloadTest
// 的子類,所以test1會呼叫OverloadTest中的方法。
OverloadTest1 test1 = new OverloadTest1();

try {
int i = 1, j = 2, m = 3;

// 這裡不會呼叫OverloadTest1的fun方法
// test.fun(i, m, j);
test1.fun(i, j, m);
test1.fun();
// 這個呼叫不會執行,因為fun3()在OverloadTest中訪問許可權是priavte
//test1.fun3();
test1.fun3(i);
} catch(Exception e) { }
}
}


class OverloadTest1 extends OverloadTest{
// 在子類中過載fun
public void fun(int i, int m, int n) {
System.out.println("Overload fun1 in OverloadTest1, parameter type: int, int, int");
}

// 這個不是對父類中方法的過載,只是一個新的方法。
public void fun3(int i) {
System.out.println("fun2 in OverloadTest1");
}
}

// 對override測試的檔案:OverrideTest.java
public class OverrideTest {
public void fun() throws TestException {
System.out.println("method fun in OverrideTest");
}

private void fun1() {
System.out.println("method fun1 in OverrideTest");
}

public static void main(String[] args) {
OverrideTest test = new OverrideTest1();
try {
test.fun();
test.fun1();
} catch(Exception e) { }
}
}

class OverrideTest1 extends OverrideTest{
// 以下正常Override
public void fun() throws TestException2 {
System.out.println("fun in OverrideTest1");
}

// 不能Override父類中的方法,因為它定義了不同的異常型別和
// 返回值。
//public int fun() throws TestException1 {
// System.out.println("method fun in Test");
// return 1;
//}

// 不能Override父類中的方法,因為它丟擲了比父類中非法範圍
// 更大的異常。
//public void fun() throws Exception {
// System.out.println("fun in OverrideTest1");
//}

// 這個方法並沒有Override父類中的fun1方法,因為這個方法在
// 父類是private型別,所以這裡只是相當於定義了一個新方法。
public void fun1() {
System.out.println("method fun1 in Test");
}
}

class TestException extends Exception{
public TestException(String msg) {
super(msg);
}
}

class TestException1 extends TestException {
public TestException1(String msg) {
super(msg);
}
}

class TestException2 extends TestException {
public TestException2(String msg) {
super(msg);
}
}