中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中可變參數常見用法有哪些

發布時間:2021-09-28 10:24:10 來源:億速云 閱讀:132 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關Java中可變參數常見用法有哪些的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

1. 用數組包裹實參

“用數組包裹實參”的做法可以分成三步:首先,為這個方法定義一個數組型的參數;然后在調用時,生成一個包含了所有要傳遞的實參的數組;最后,把這個數組作為一個實參傳遞過去。

這種做法可以有效的達到“讓方法可以接受個數可變的參數”的目的,只是調用時的形式不夠簡單。

J2SE 1.5中提供了Varargs機制,允許直接定義能和多個實參相匹配的形參。從而,可以用一種更簡單的方式,來傳遞個數可變的實參。

Varargs的含義

大體說來,“Varargs”是“variable number of arguments”的意思。有時候也被簡單的稱為“variable arguments”,不過因為這一種叫法沒有說明是什么東西可變,所以意義稍微有點模糊。

2. 定義實參個數可變的方法

只要在一個形參的“類型”與“參數名”之間加上三個連續的“.”(即“...”,英文里的句中省略號),就可以讓它和不確定個實參相匹配。而一個帶有這樣的形參的方法,就是一個實參個數可變的方法。

清單1:一個實參個數可變的方法

private static int sumUp(int... values) {}

注意,只有最后一個形參才能被定義成“能和不確定個實參相匹配”的。因此,一個方法里只能有一個這樣的形參。另外,如果這個方法還有其它的形參,要把它們放到前面的位置上。

編譯器會在背地里把這最后一個形參轉化為一個數組形參,并在編譯出的class文件里作上一個記號,表明這是個實參個數可變的方法。

清單2:實參個數可變的方法的秘密形態

private static int sumUp(int[] values) {}

由于存在著這樣的轉化,所以不能再為這個類定義一個和轉化后的方法簽名一致的方法。

清單3:會導致編譯錯誤的組合

private static int sumUp(int... values) {}private static int sumUp(int[] values) {}

3. 調用實參個數可變的方法

只要把要傳遞的實參逐一寫到相應的位置上,就可以調用一個實參個數可變的方法。不需要其它的步驟。

清單4:可以傳遞若干個實參

sumUp(1, 3, 5, 7);

在背地里,編譯器會把這種調用過程轉化為用“數組包裹實參”的形式:

清單5:偷偷出現的數組創建

sumUp(new int[]{1, 2, 3, 4});

另外,這里說的“不確定個”也包括零個,所以這樣的調用也是合乎情理的:

清單6:也可以傳遞零個實參

sumUp();

這種調用方法被編譯器秘密轉化之后的效果,則等同于這樣:

清單7:零實參對應空數組

sumUp(new int[]{});

注意這時傳遞過去的是一個空數組,而不是null。這樣就可以采取統一的形式來處理,而不必檢測到底屬于哪種情況。

4. 處理個數可變的實參

處理個數可變的實參的辦法,和處理數組實參的辦法基本相同。所有的實參,都被保存到一個和形參同名的數組里。根據實際的需要,把這個數組里的元素讀出之后,要蒸要煮,就可以隨意了。

清單8:處理收到的實參們

private static int sumUp(int... values) { int sum = 0; for (int i = 0; i < values.length; i++) { sum += values[i]; } return sum;}

5. 轉發個數可變的實參

有時候,在接受了一組個數可變的實參之后,還要把它們傳遞給另一個實參個數可變的方法。因為編碼時無法知道接受來的這一組實參的數目,所以“把它們逐一寫到該出現的位置上去”的做法并不可行。不過,這并不意味著這是個不可完成的任務,因為還有另外一種辦法,可以用來調用實參個數可變的方法。

在J2SE 1.5的編譯器的眼中,實參個數可變的方法是最后帶了一個數組形參的方法的特例。因此,事先把整組要傳遞的實參放到一個數組里,然后把這個數組作為最后一個實參,傳遞給一個實參個數可變的方法,不會造成任何錯誤。借助這一特性,就可以順利的完成轉發了。

清單9:轉發收到的實參們

public class PrintfSample { public static void main(String[] args) {  printOut("Pi:%f E:%f\n", Math.PI, Math.E); } private static void printOut(String format, Object... args) {  System.out.printf(format, args); }}

6. 是數組?不是數組?

盡管在背地里,編譯器會把能匹配不確定個實參的形參,轉化為數組形參;而且也可以用數組包了實參,再傳遞給實參個數可變的方法;但是,這并不表示“能匹配不確定個實參的形參”和“數組形參”完全沒有差異。

一個明顯的差異是,如果按照調用實參個數可變的方法的形式,來調用一個最后一個形參是數組形參的方法,只會導致一個“cannot be applied to”的編譯錯誤。

清單10:一個“cannot be applied to”的編譯錯誤

private static void testOverloading(int[] i) {System.out.println("A");}public static void main(String[] args) {testOverloading(1, 2, 3);//編譯出錯}

由于這一原因,不能在調用只支持用數組包裹實參的方法的時候(例如在不是專門為J2SE 1.5設計第三方類庫中遺留的那些),直接采用這種簡明的調用方式。

如果不能修改原來的類,為要調用的方法增加參數個數可變的版本,而又想采用這種簡明的調用方式,那么可以借助“引入外加函數(Introduce Foreign Method)”和“引入本地擴展(Intoduce Local Extension)”的重構手法來近似的達到目的。

7. 當個數可變的實參遇到泛型

J2SE 1.5中新增了“泛型”的機制,可以在一定條件下把一個類型參數化。例如,可以在編寫一個類的時候,把一個方法的形參的類型用一個標識符(如T)來代表,至于這個標識符到底表示什么類型,則在生成這個類的實例的時候再行指定。這一機制可以用來提供更充分的代碼重用和更嚴格的編譯時類型檢查。

不過泛型機制卻不能和個數可變的形參配合使用。如果把一個能和不確定個實參相匹配的形參的類型,用一個標識符來代表,那么編譯器會給出一個“generic array creation”的錯誤。

清單11:當Varargs遇上泛型

private static void testVarargs(T... args) {//編譯出錯}

造成這個現象的原因在于J2SE 1.5中的泛型機制的一個內在約束——不能拿用標識符來代表的類型來創建這一類型的實例。在出現支持沒有了這個約束的Java版本之前,對于這個問題,基本沒有太好的解決辦法。

不過,傳統的“用數組包裹”的做法,并不受這個約束的限制。

清單12:可以編譯的變通做法

private static void testVarargs(T[] args) { for (int i = 0; i < args.length; i++) { System.out.println(args[i]); }}

8. 重載中的選擇問題

Java支持“重載”的機制,允許在同一個類擁有許多只有形參列表不同的方法。然后,由編譯器根據調用時的實參來選擇到底要執行哪一個方法。

傳統上的選擇,基本是依照“特殊者優先”的原則來進行。一個方法的特殊程度,取決于為了讓它順利運行而需要滿足的條件的數目,需要條件越多的越特殊。

在引入Varargs機制之后,這一原則仍然適用,只是要考慮的問題豐富了一些——傳統上,一個重載方法的各個版本之中,只有形參數量與實參數量正好一致的那些有被進一步考慮的資格。但是Varargs機制引入之后,完全可以出現兩個版本都能匹配,在其它方面也別無二致,只是一個實參個數固定,而一個實參個數可變的情況。

遇到這種情況時,所用的判定規則是“實參個數固定的版本優先于實參個數可變的版本”。

清單13:實參個數固定的版本優先

如果在編譯器看來,同時有多個方法具有相同的優先權,它就會陷入無法就到底調用哪個方法作出一個選擇的狀態。在這樣的時候,它就會產生一個“reference to 被調用的方法名 is ambiguous”的編譯錯誤,并耐心的等候作了一些修改,足以免除它的迷惑的新源代碼的到來。

在引入了Varargs機制之后,這種可能導致迷惑的情況,又增加了一些。例如現在可能會有兩個版本都能匹配,在其它方面也如出一轍,而且都是實參個數可變的沖突發生。

public class OverloadingSampleA { public static void main(String[] args) { testOverloading(1);//打印出A testOverloading(1, 2);//打印出B testOverloading(1, 2, 3);//打印出C } private static void testOverloading(int i) { System.out.println("A"); } private static void testOverloading(int i, int j) { System.out.println("B"); } private static void testOverloading(int i, int... more) { System.out.println("C"); }}

如果在編譯器看來,同時有多個方法具有相同的優先權,它就會陷入無法就到底調用哪個方法作出一個選擇的狀態。在這樣的時候,它就會產生一個“reference to 被調用的方法名 is ambiguous”的編譯錯誤,并耐心的等候作了一些修改,足以免除它的迷惑的新源代碼的到來。

在引入了Varargs機制之后,這種可能導致迷惑的情況,又增加了一些。例如現在可能會有兩個版本都能匹配,在其它方面也如出一轍,而且都是實參個數可變的沖突發生。

清單14:左右都不是,為難了編譯器

public class OverloadingSampleB { public static void main(String[] args) { testOverloading(1, 2, 3);//編譯出錯 } private static void testOverloading(Object... args) { } private static void testOverloading(Object o, Object... args) { }}

另外,因為J2SE 1.5中有“Autoboxing/Auto-Unboxing”機制的存在,所以還可能發生兩個版本都能匹配,而且都是實參個數可變,其它方面也一模一樣,只是一個能接受的實參是基本類型,而另一個能接受的實參是包裹類的沖突發生。

清單15:Autoboxing/Auto-Unboxing帶來的新問題

public class OverloadingSampleC { public static void main(String[] args) { /* 編譯出錯 */ testOverloading(1, 2); /* 還是編譯出錯 */ testOverloading(new Integer(1), new Integer(2)); } private static void testOverloading(int... args) { } private static void testOverloading(Integer... args) { }}

感謝各位的閱讀!關于“Java中可變參數常見用法有哪些”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

敦煌市| 绍兴市| 曲松县| 水富县| 澎湖县| 普兰店市| 固阳县| 黑山县| 卢龙县| 文水县| 师宗县| 拜泉县| 左贡县| 兴城市| 会理县| 根河市| 鹤山市| 南皮县| 衡山县| 航空| 长葛市| 平罗县| 太和县| 遂平县| 昂仁县| 宁强县| 墨脱县| 周至县| 金堂县| 南乐县| 满城县| 庆阳市| 伊川县| 勃利县| 裕民县| 洪江市| 翁牛特旗| 绥德县| 缙云县| 奉贤区| 宜良县|