納尼?Java種的重載還有靜態綁定這種說法?

流量如水,文章就是一個瓶子,標題是瓶口,內容是瓶身。 瓶子裝水有多快依賴瓶口大小,瓶子裝水有多少依賴瓶身大小。

什麼是重載?

在同一個類中,如果多個方法有相同的方法名稱,不同的參數類型,參數個數,參數順序,即稱爲重載,比如一個類中有多個構造方法。
String 類中的 valueOf 是比較著名的重載案例,它有9個方法,可以將輸入的基本數據類型、數組、Object 等轉化稱爲字符串。在編譯器的眼裏,方法名稱+參數列表,組成了一個唯一鍵,稱爲方法簽名,JVM 通過這個唯一鍵決定調用哪種重載的方法。注意,方法返回值並非是這個組合體中的一員,所以在使用重載機制時,不能有兩個方法名稱完全相同,參數類型和個數也相同,但是返回類型不相同的方法,如下實例代碼:

public class Student {
	public void methodOverload() {}

	// 編譯出錯,返回值並不是方法簽名的一部分
	public int methodOverload() {
		return 7;
	}
	
	// 編譯出錯,訪問修飾符也不是方法簽名的一部分
	private void methodOverload() {}

	// 編譯出錯,final 修飾符也不是方法簽名的一部分
	private final void methodOverload() {}

	// 編譯出錯,static 修飾符也不是方法簽名的一部分
	public static void methodOverload() {}
}

重載的調用規則是什麼?

重載似乎是比較容易理解和掌握的編程技能了,有時候僅僅憑藉肉眼就能知道應調用哪個重載方法,那麼看如下實例代碼,如果調用 methodOverload(7) ,猜一下到底調用的是誰呢(JDK11 環境)?

public class OverloadMethods {
	// 1.無參方法
	public void methodOverload() {
		System.out.println("無參方法");
	}

	// 2.基本數據類型
	public void methodOverload(int param) {
		System.out.println("參數爲基本類型 int 的方法");
	}

	// 3.包裝數據類型
	public void methodOverload(Integer param) {
		System.out.println("參數爲包裝類型 Integer 的方法");
	}

	// 4.可變參數,可以接受 0 ~ n 個 Integer 對象
	public void methodOverload(Integer param) {
		System.out.println("可變參數方法");
	}

	// 5.Object 對象
	public void methodOverload(Object param) {
		System.out.println("參數爲 Object 的方法");
	}
}

JVM 在重載方法中,選擇合適的目標方法的順序如下:

  • 精確匹配
  • 如果是基本數據類型,自動轉換爲更大表示範圍的基本類型
  • 通過自動拆箱與裝箱
  • 通過子類向上轉型繼承路線依次匹配
  • 通過可變參數匹配

精確匹配優先,這是無容置疑的,int 在和 Integer 的較量中勝出,因爲不需要自動裝箱,所以 7 會調用 int 參數的方法。也就是第2種方法,你猜對了嗎?如果是 new Integer(7) 的話,Integer 參數的方法勝出。
如果本方法只有 methodOverload(long) ,則可以接收 methodOverload(3) 的實參調用;反之,如果只有 methodOverload(int) ,而傳入 long 值,則會編譯出錯。基本數據類型轉化爲表示範圍更大的基本數據類型優先於自動裝箱,即 int 轉爲 long ,優先於裝箱爲 Integer ,所以會發生編譯錯誤。
注意,null 可以匹配任何類對象,在查找目標方法時,是從最底層子類依次向上查找的,在本次實例中,如果 methodOverload(null) ,則會調用參數爲 Integer 的方法。爲什麼呢?

1. 因爲 Integer 是一個類
2. 它是 Object 的子類

在示例代碼中,如果還有單個 String 類型參數的方法,則會編譯出錯,因爲 null 不知道該選擇 Integer 還是 String。根據上述規則,可變參數的優先級別是最低的,但是如果調用 methodOverload(13,14) ,此時有兩個參數,雖然有自動裝箱的開銷,但可變參數仍然會執行這種方法請求。

父類的共有實例方法與子類的共有實例方法可以存在重載關係。不管繼承關係如何複雜,重載在編譯時可以根據規則知道調用哪種目標方法。所以,重載又稱爲靜態綁定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章