Java方法重載

如果一個類中有多個具有相同名稱但參數不同的方法,則稱爲方法重載。如果只需要執行一個操作,具有相同的方法名稱將增加程序的可讀性。

假設必須執行給定數值的添加操作(求和),但是參數的數量不固定,如果爲兩個參數編寫add1(int,int)方法,爲三個參數編寫add2(int,int,int)方法,可能對其他程序員來說很難理解這樣的方法的行爲,因爲它的名稱不同。

因此,執行方法重載能比較容易理解程序含義。

方法重載的優點

  • 方法重載提高了程序的可讀性。

重載方法不同的方式

在java中重載方法有兩種方式,它們分別是:

  • 通過改變參數的數量
  • 通過更改數據類型

注意:在java中,只通過更改方法的返回類型來實現方法重載是不可以的。

1. 方法重載: 修改參數的數量

在這個例子中,我們將創建了兩個方法,第一個add()方法執行兩個數值的相加操作,第二個add()方法執行三個數值的相加操作。

在這個例子中,我們創建靜態方法,所以不需要創建實例來調用方法。

class Adder {
    static int add(int a, int b) {
        return a + b;
    }

    static int add(int a, int b, int c) {
        return a + b + c;
    }
}

class TestOverloading1 {
    public static void main(String[] args) {
        System.out.println(Adder.add(11, 11));
        System.out.println(Adder.add(11, 11, 11));
    }
}

上面代碼執行後,輸出結果如下 -

22
33

2. 方法重載:更改參數的數據類型

在這個例子中,創建了兩種數據類型不同的方法。 第一個add方法接收兩個整數參數,第二個add方法接收兩個雙精度型參數。

class Adder {
    static int add(int a, int b) {
        return a + b;
    }

    static double add(double a, double b) {
        return a + b;
    }
}

class TestOverloading2 {
    public static void main(String[] args) {
        System.out.println(Adder.add(11, 11));
        System.out.println(Adder.add(12.3, 12.6));
    }
}

上面代碼執行後,輸出結果如下 -

22
24.9

問題:爲什麼方法重載不能通過更改方法的返回類型?

在java中,只通過改變方法的返回類型來實現方法重載是不可能的,因爲這樣具有模糊性。 讓我們來看看模糊性是怎麼樣發生的:

class Adder {
    static int add(int a, int b) {
        return a + b;
    }

    static double add(int a, int b) {
        return a + b;
    }
}

class TestOverloading3 {
    public static void main(String[] args) {
        System.out.println(Adder.add(11, 11));// ambiguity
    }
}

上面代碼執行後,輸出結果如下 -

Compile Time Error: method add(int,int) is already defined in class Adder

System.out.println(Adder.add(11,11));//這裏,java如何確定應該調用哪個sum()方法?

注意:編譯時錯誤優於運行時錯誤。 所以,如果你聲明相同的方法具有相同的參數,java編譯器渲染編譯器時間錯誤。

可以重載java main()方法嗎?

這是完全可以的。 可以通過方法重載在類中有任意數量的main方法。 但是JVM調用main()方法,它只接收字符串數組作爲參數。 讓我們來看一個簡單的例子:

class TestOverloading4{  
    public static void main(String[] args){System.out.println("main with String[]");}  
    public static void main(String args){System.out.println("main with String");}  
    public static void main(){System.out.println("main without args");}  
}

上面代碼執行後,輸出結果如下 -

main with String[]

方法重載和類型提升

如果沒有找到匹配的數據類型,那麼會隱式地將一個類型提升到另一個類型。 讓我們通過下面的圖示來理解這個概念:
Java方法重載

如上圖所示,byte可以被提升爲shortintlongfloatdoubleshort數據類型可以提升爲intlongfloatdoublechar數據類型可以提升爲intlongfloatdouble等等。

使用類型提升方法重載的示例

class OverloadingCalculation1 {
    void sum(int a, long b) {
        System.out.println(a + b);
    }

    void sum(int a, int b, int c) {
        System.out.println(a + b + c);
    }

    public static void main(String args[]) {
        OverloadingCalculation1 obj = new OverloadingCalculation1();
        obj.sum(20, 20);// now second int literal will be promoted to long
        obj.sum(20, 20, 20);

    }
}

上面代碼執行後,輸出結果如下 -

40
60

如果找到匹配使用類型提升方法重載示例
如果方法中存在匹配類型參數,則不會執行類型提升方法重載。

class OverloadingCalculation2 {
    void sum(int a, int b) {
        System.out.println("int arg method invoked");
    }

    void sum(long a, long b) {
        System.out.println("long arg method invoked");
    }

    public static void main(String args[]) {
        OverloadingCalculation2 obj = new OverloadingCalculation2();
        obj.sum(20, 20);// now int arg sum() method gets invoked
    }
}

上面代碼執行後,輸出結果如下 -

Output:int arg method invoked

在模糊的情況下使用類型提升來實現方法重載的示例

如果在方法中沒有匹配的類型參數,並且每個方法都會提升相同數量的參數,那麼會出現歧義。如下示例代碼,將會產生編譯時錯誤。

class OverloadingCalculation3 {
    void sum(int a, long b) {
        System.out.println("a method invoked");
    }

    void sum(long a, int b) {
        System.out.println("b method invoked");
    }

    public static void main(String args[]) {
        OverloadingCalculation3 obj = new OverloadingCalculation3();
        obj.sum(20, 20);// now ambiguity
    }
}

注意: 只有一種類型不被隱式地去提升,例如double不能被隱含地提升到任何類型。