重載


視使用情境或條件的不同,建構物件時也許希望有對應的初始流程,你可以定義多個建構式,只要參數型態或個數不同,這稱之為重載(Overload)建構式。例如:

public class Some {
    private int a = 10;
    private String text = "n.a.";
    public Some(int a) {
        if(a > 0) {
            this.a = a;
        }
    }
    public Some(int a, String text) {
        if(a > 0) {
            this.a = a;
        }
        if(text != null) {
            this.text = text;
        }
    }
    ...
}

在這個程式碼片段中,建構時有兩種選擇,一是使用new Some(100)的方式,另一個是使用new Some(100, "some text")的方式。

有些場合建議,如果定義了有參數的建構式,也可以加入無參數建構式,即使內容為空也無所謂,這是為了日後使用上的彈性,例如運用反射(Reflection)機制生成物件的需求,或者是繼承時呼叫父類別建構式時的方便。

定義方法時也可以進行重載,可為類似功能的方法提供統一名稱,但根據參數型態或個數的不同呼叫對應的方法。以String類別為例,其valueOf()方法就提供了多個版本:

public static String valueOf(boolean b)
public static String valueOf(char c)
public static String valueOf(char[] data)
public static String valueOf(char[] data, int offset, int count)
public static String valueOf(double d)
public static String valueOf(float f)
public static String valueOf(int i)
public static String valueOf(long l)
public static String valueOf(Object obj)

雖然呼叫的方法名稱都是valueOf(),但根據傳遞的引數型態不同,會呼叫對應的方法,例如呼叫String.valueOf(10),因為10是int型態,所以會執行valueOf(int i)的版本,若是String.valueOf(10.12),因為10.12是double型態,會執行valueOf(double d)的版本(片段中看到的static之後就會說明)。

方法重載讓程式設計人員不用苦惱方法名稱的設計,可用一致的名稱來呼叫類似功能的方法,方法重載可根據傳遞引數的型態不同,也可根據參數列個數的不同來設計方法重載。例如:

public class SomeClass {
    public void someMethod() {
    }
    public void someMethod(int i) {
    }
    public void someMethod(float f) {
    }
    public void someMethod(int i, float f) {
    }
}

返回值型態不可作為方法重載依據,例如以下方法重載並不正確,編譯器會將兩個someMethod()視為重複定義而編譯失敗:

public class Some {
    public int someMethod(int i) {
        return 0;
    }
    public double someMethod(int i) {
        return 0.0;
    }

在JDK5之後使用方法重載時,要注意自動裝箱、拆箱問題,來看看以下程式的結果會是什麼?

package cc.openhome;

class Some {
    void someMethod(int i) {
        System.out.println("int 版本被呼叫");
    }
    void someMethod(Integer integer) {
        System.out.println("Integer 版本被呼叫");
    }
}

public class OverloadBoxing {
    public static void main(String[] args) {
        Some s = new Some();
        s.someMethod(1);
    }
}

結果是顯示「int 版本被呼叫」,如果想呼叫參數為Integer版本的方法,要明確指定。例如:

s.someMethod(new Integer(1));

編譯器在處理重載方法時,會依以下順序來處理:

  • 還沒有裝箱動作前可符合引數個數與型態的方法
  • 裝箱動作後可符合引數個數與型態的方法
  • 嘗試有不定長度引數並可符合引數型態的方法
  • 找不到合適的方法,回報編譯錯誤