1. 程式人生 > >Java-多型、方法過載

Java-多型、方法過載

什麼是多型、過載

1. 多型

對多型現象的理解

多型是面向物件的一個重要特徵。關於定義性的概念,相信網上有很多資料,不再多說。這裡說說我自己的理解。多型是指在執行期間,呼叫某個類物件的方法會有不同的行為。舉個最普遍的例子來說:

基類:Shape

class Shape{
    public void draw();
    public void clear();
}

子類: Circle 、Rectangle

class Circle extends Shape{
    public void draw(); //畫一個圓
    public void clear();
}

class
Rectangle extends Shape{
public void draw(); //畫一個長方形 public void clear(); }

如果我宣告一個Shape類的引用,然後初始化,最後呼叫這個物件的draw()方法:

Shape mShape = null;
mShape = init();
mShape.draw();

由於Rectangle類的物件和Circle類的物件都可以向上轉換為Shape的物件,所以當我呼叫mShape.draw()方法後,可能會畫一個圓,也有可能會畫一個長方形,這完全取決於init()方法返回的物件是什麼。這種現象稱為多型,而且這種現象在現實中是普遍存在的,例如對

來說,有汽車電動車,車都有行駛行為,對不同的車來說,會採取不同的實際行動來執行行駛這個行為,這是多型在現實中的體現。

多型發生的時機

多型發生在執行期間,這是因為不到實際執行時,我們永遠不知道init()方法返回的到底是哪個實際的物件,因此多型會推遲到執行期間發生。但是當方法是static或final修飾時,在編譯期間便進行繫結。原因是final方法不允許重寫,而static方法是跟類繫結的,與物件無關。

2.過載

很多人會將過載跟多型混淆,多型的發生必須要有繼承、重寫 , 而過載不一樣,過載是指同一個方法名(只指的是名字),有多個不同的版本,例如我們要寫一個add方法,如果是兩個數字,返回求和後的字串。如果是兩個字串,我們就將字串聯接起來。寫成程式碼就是如下的樣子:

class Example{
    public String addInt(int a , int b){
        return (a + b) + "";
    }

    public String addString(String a , String b){
        StringBuilder temp = new StringBuilder();
        temp.append(a);
        temp.append(b);
        return temp.toString();
    }
}

但是這樣會有很多不同的方法,容易造成混淆。我們編寫一個方法的多個不同版本,根據傳入的引數不同,呼叫不同版本的方法。因此就有方法過載。

class Example{
    public String add(int a , int b){
        return (a + b);
    }

    public String add(String a , String b){ 
        StringBuilder temp = new StringBuilder();
        temp.append(a);
        temp.append(b);
        return temp.toString();
    }
}

根據傳入引數的不同,編譯器會呼叫不同版本的方法。

過載發生的時機

由於方法呼叫的引數是編譯期確定的,因此過載發生在編譯期

過載時方法匹配的優先順序

  1. 根據呼叫的方法名,查詢是否有定義好的同名方法,如果沒有就會報錯
  2. 比較形參和實參的數目是否相等,如果沒有則會報錯。如果有一個或多個方法符合條件,這些方法進入候選集
  3. 與候選集中的方法比較引數表,如果對應位置上的每個引數型別完全匹配,或者可以通過擴充套件轉換相匹配,則該方法稱為可行方法,併入可行集。若不存在可行方法,則會報錯
  4. 在可行集中按照下面的原則選取最佳可行方法,若最佳可行方法為0 則會報錯,否則最佳可行方法就是最終確定要呼叫的方法

獲取的原則是
1. 若每一個引數都可以完全匹配,它就是最佳可行方法
2. 若某個方法的每一個引數都不比別的方法差,且至少有一個引數比別的方法好,它就是最佳可行方法,這裡的差和好是指,完全匹配要比擴充套件轉化好,不過同樣是擴充套件轉換,仍然存在好和差的問題,擴充套件轉換有兩條路徑
byte-short-int-long-float-double
char-int-long-float-double
這兩條路徑中位於左邊的型別都可以轉換為右邊的型別,不過源型別與目標型別的距離越近,則這種轉化就越好。
3. 如果存在自動裝箱和變長引數,則擴充套件轉換的優先順序大於自動裝箱,自動裝箱的優先順序大於變長引數。