日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

类与接口(四)方法重载解析

發布時間:2025/3/20 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 类与接口(四)方法重载解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

###一、方法重載簡介

方法重載: 當兩個(或多個)方法的名稱相同,而參數的對應類型或個數不同時,我們就說方法重載了。當然,編譯器也能識別出來。

編譯器是如何識別調用了哪個方法?

在往下講前,我們先來了解一下:編譯器是怎么才能識別出程序調用了那個方法。其實,這個問題就是在問:在調用方法處,編譯器能得到調用方法的什么信息,從而能找到對應的方法?我們一般的方法調用是這樣的:

method( vars );

也就是說,方法調用處,一共為編譯器提供兩個信息:方法名、參數列表。
所以,編譯器只能通過 方法名 和 參數列表 來識別調用方法

有一道面試題問:為什么不能通過返回類型來重載方法?
就是上面所說的,方法調用處并沒有提供返回類型的信息,所以當多個方法只有返回類型不一樣時,編譯器就不知道調用了那個方法了。

我們已經知道了編譯器是怎么識別方法的了,而對于方法重載,其要求方法名是一樣的,那么我們只需要關注 參數列表 便可以了參數列表區分,或者說重載方法的區分:

  • 參數的個數
  • 參數的類型
  • 參數的順序

###二、方法重載的匹配選擇

方法重載后,方法調用處可能會遇到應該選擇哪個重載方法的問題,如果只有唯一個重載方法可以匹配,那么就沒問題。然而,大部分情況卻是有多個重載方法是可以匹配的,那么這時候就應該選擇最合適的重載方法.

匹配最合適、最明確的重載方法,其實就是實參列表去匹配當前重載方法中形參列表,尋找與實參列表最相近的形參列表
##1、基本類型之間的重載

對于基本類型來說,從“短類型”擴展成“長類型”是默認允許、自動進行的,這就可能造成了實參可能匹配到多個“長類型”的形參,看個簡單例子:

public static void main(String[] args) {short s = 4;m(s); }public static void m(int x){//方法一System.out.println("重載方法一"); }public static void m(float x){//方法二System.out.println("重載方法二"); }

運行結果

重載方法一

short類型 可以默認自動轉換成int、'float’類型。但m(s)真正匹配選擇的是m(int x)方法,而不是形參長度更長的m(float x)。所以可以看出,基本類型的形參匹配規則是: 如果沒有匹配到精確類型的形參,則優先匹配 存儲長度(范圍)大于且是最接近實參的存儲長度的形參,從而確定調用哪個重載方法
##2、引用類型間的重載

對于引用類型來說,可以匹配到多個重載方法的原因是:引用類型的對象進行類型上轉也是JVM默認自動進行的,那么就可能匹配多個祖先類型的形參看下面的例子:

public class Test_3 {public static void main(String[] args) {Children children = new Children();someMethod(children); } public static void someMethod(Ancestor an) {//重載方法1System.out.println("this is Ancestor Method!"); }public static void someMethod(Parent an) {//重載方法2System.out.println("this is Parent Method!"); } }//3個具有繼承關系的類 class Ancestor{//祖先類 }class Parent extends Ancestor{//父類,繼承于Ancestor }class Children extends Parent{//子類,繼承于Parent }

運行結果

this is Parent Method!

可以看出,引用類型與基本類型一樣,都是選擇”最明確的方法“, 引用類型間選擇最明確的重載方法的規則是: 如果找不到重載方法的形參的引用類型與實參一致,則實參優先匹配 在繼承樹結構上,離實參類型最近的形參,則此形參所在的重載方法便是最明確的重載方法。
##3、自動裝箱拆箱、可變參數類型

裝箱拆箱、以及可變參數列表的處理都是由編譯器自動處理,也就是說是默認自動進行的,這同樣會讓實參列表可以匹配多個形參列表 ,可以匹配多個重載方法

此小節將會涉及到基本類型、引用類型、自動裝箱拆箱可變參數的重載方法匹配的優先級。

看下面的例子,這個例子包括很多情況:

public class Test_3 {public static void main(String[] args) {short s = 5; overloadMethod(s);// test1Integer i = 10;overloadMethod(i);//test2overloadMethod(s,s);//test3 } public static void overloadMethod(int a) { //m1System.out.println("調用 overloadMethod(int)"); }public static void overloadMethod(Short in) {//m2System.out.println("調用 overloadMethod(short)"); }public static void overloadMethod(int a,int b) {//m3System.out.println("調用 overloadMethod(int,int)"); }public static void overloadMethod(short... s) { //m4System.out.println("調用 overloadMethod(short...)"); }public static void overloadMethod(Integer... i) {//m5System.out.println("調用 overloadMethod(Integer...)"); } }

運行結果

調用 overloadMethod(int)
調用 overloadMethod(int)
調用 overloadMethod(int,int)

我們來分析一下上面的例子中,方法調用處可以匹配到的方法:

  • test1 處的方法調用可以匹配的重載方法有:m1(基本類型的短類型自動轉為長類型)、m2(自動裝箱)、m4(可變參數列表)
  • test2 處的方法調用可以匹配的重載方法有:m1(自動拆箱)、m5(可變參數列表);
  • test3 處的方法調用可以匹配的重載方法有:m3(基本類型的短類型自動轉換成長類型)、m4(可變參數列表)

查看輸出結果,發現:test1處選擇了m1、test2選擇了m1,test3選擇了m3。
根據這樣的結果,也就是這幾種形參匹配規則還是有個匹配的順序的。對重載方法的選擇作以下總結:

  • 先按照實參的類型(基本類型或引用類型)對應匹配規則,進行查找最相近的形參列表,從而找到最明確的重載方法;找不到,則執行第二步;
  • 對實參進行裝箱或拆箱轉換(前提是實參是基本類型或者是包裝類),再安按照轉換得到的類型進行匹配形參的類型(形參類型與轉換類型要一致,特別注意基本類型);找不到,則執行第三步;
  • 匹配形參是可變參數的重載方法,此時,形參的類型可以是 實參的類型以及通過 基本類型的短轉長、自動裝箱拆箱、祖先類型 得到的轉換類型。

將上面的總結再簡化一下,可以簡化成 重載方法的形參匹配規則的優先級:

當前類型(基本類型或引用類型)的匹配規則 > 自動裝箱拆箱 > 可變參數列表

再看一個例子:

public class MyTest {public static void main(String[] args) {int a = 5;short s = 8;m(a,s);}public static void m(int a,Short b) {//m1System.out.println("調用了m(int,Short)"); }public static void m(float f,short s) {//m2System.out.println("調用了m(float,short)"); } }

運行結果

調用了m(float,short)

分析: 實參都是基本類型,優先考慮形參列表都是基本類型的重載方法,找不到才考慮自動裝箱拆箱
##4、泛型方法的重載

泛型方法的重載規則: 將泛型方法的類型變量擦除,然后與非泛型方法一樣,按照上面所說的三種規則一一匹配

public static void main(String[] args) { //創建Runnable對象 Runnable r = new Runnable() { public void run(){} }; //調用泛型方法m(r); }public static <T> void m(T t) {//m1System.out.println("調用了<T> void m(T)"); }public static <T extends Runnable> void m(T t) {//m2System.out.println("調用了<T extends Runnable> void m(T t)"); }

運行結果

調用了 void m(T t)

上面的兩個泛型方法m(T t)進行類型擦除后是:

public static void m(Object t);public static void m(Runnable t);

顯然,調用方法應該是m2,與運行結果相符;
##5. 沒法確定的重載方法調用

盡管編譯器會按照上面所說的三種優先級別去讓實參匹配形參,然而匹配的結果卻不一定是唯一的,也就是說會匹配到多個方法,從而無法確定調用那個方法,編譯失敗

情況一: 實參列表的所有最佳匹配的形參不在同一個方法中

public class MyTest {public static void main(String[] args) {int aa = 5;short ss = 8;m(aa,ss);//編譯不通過,無法確定調用了那個重載方法}public static void m(int a,double b) {//m1System.out.println("調用了m(int,Short)"); }public static void m(float f,int c) {//m2System.out.println("調用了m(float,short)"); } }

分析

m(aa,ss)的調用編譯失敗,因為實參aa的最佳匹配m(int,double)的第一個形參,而實參ss的最佳匹配則是m(float,short)的第二個形參。
因此,實參列表的(aa,ss)的最佳形參類型匹配分開在了兩個重載方法中。
注意一下,即使某個重載方法的形參列表包含最多的最相近的形參類型,只要不是全部,那么依舊無法確定調用了哪個重載方法。

情況二可變參數列表的特殊性 – 無法根據可變參數的類型來重載方法

public static void m(short... s) {}public static void m(Short... s) {}public static void m(int... s) {}

調用測試例子:

short s = 8; Short sl = 10; m(s,s);//編譯不通過 m(s,sl);//編譯不通過 m(sl,sl);//編譯不通過

##重寫 與 重載的區別

  • 重寫是針對父類與子類間的方法,即必須先得繼承父類的方法。而重載則沒有這種限制。
  • 重寫要求方法的 而方法重載則只需要 方法名相同,參數列表不同就行了。
  • 方法重載時,方法的調用是在編譯時期就已經確定了調用那個方法;方法重寫,則要在運行時,才能確定調用的是子類還是父類的方法。

作者:jinggod
出處:http://www.cnblogs.com/jinggod/p/8503150.html

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的类与接口(四)方法重载解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。