<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### [可變參數列表](https://lingcoder.gitee.io/onjava8/#/book/06-Housekeeping?id=%e5%8f%af%e5%8f%98%e5%8f%82%e6%95%b0%e5%88%97%e8%a1%a8) 你可以以一種類似 C 語言中的可變參數列表(C 通常把它稱為"varargs")來創建和調用方法。這可以應用在參數個數或類型未知的場合。由于所有的類都最后繼承于**Object**類(隨著本書的進展,你會對此有更深的認識),所以你可以創建一個以 Object 數組為參數的方法,并像下面這樣調用: ~~~ // housekeeping/VarArgs.java // Using array syntax to create variable argument lists class A {} public class VarArgs { static void printArray(Object[] args) { for (Object obj: args) { System.out.print(obj + " "); } System.out.println(); } public static void main(String[] args) { printArray(new Object[] {47, (float) 3.14, 11.11}); printArray(new Object[] {"one", "two", "three"}); printArray(new Object[] {new A(), new A(), new A()}); } } ~~~ 輸出: ~~~ 47 3.14 11.11 one two three A@15db9742 A@6d06d69c A@7852e922 ~~~ `printArray()`的參數是**Object**數組,使用 for-in 語法遍歷和打印數組的每一項。標準 Java 庫能輸出有意義的內容,但這里創建的是類的對象,打印出的內容是類名,后面跟著一個**@**符號以及多個十六進制數字。因而,默認行為(如果沒有定義`toString()`方法的話,后面會講這個方法)就是打印類名和對象的地址。 你可能看到像上面這樣編寫的 Java 5 之前的代碼,它們可以產生可變的參數列表。在 Java 5 中,這種期盼已久的特性終于添加了進來,就像在`printArray()`中看到的那樣: ~~~ // housekeeping/NewVarArgs.java // Using array syntax to create variable argument lists public class NewVarArgs { static void printArray(Object... args) { for (Object obj: args) { System.out.print(obj + " "); } System.out.println(); } public static void main(String[] args) { // Can take individual elements: printArray(47, (float) 3.14, 11.11); printArray(47, 3.14F, 11.11); printArray("one", "two", "three"); printArray(new A(), new A(), new A()); // Or an array: printArray((Object[]) new Integer[] {1, 2, 3, 4}); printArray(); // Empty list is OK } } ~~~ 輸出: ~~~ 47 3.14 11.11 47 3.14 11.11 one two three A@15db9742 A@6d06d69c A@7852e922 1 2 3 4 ~~~ 有了可變參數,你就再也不用顯式地編寫數組語法了,當你指定參數時,編譯器實際上會為你填充數組。你獲取的仍然是一個數組,這就是為什么`printArray()`可以使用 for-in 迭代數組的原因。但是,這不僅僅只是從元素列表到數組的自動轉換。注意程序的倒數第二行,一個**Integer**數組(通過自動裝箱創建)被轉型為一個**Object**數組(為了移除編譯器的警告),并且傳遞給了`printArray()`。顯然,編譯器會發現這是一個數組,不會執行轉換。因此,如果你有一組事物,可以把它們當作列表傳遞,而如果你已經有了一個數組,該方法會把它們當作可變參數列表來接受。 程序的最后一行表明,可變參數的個數可以為 0。當具有可選的尾隨參數時,這一特性會有幫助: ~~~ // housekeeping/OptionalTrailingArguments.java public class OptionalTrailingArguments { static void f(int required, String... trailing) { System.out.print("required: " + required + " "); for (String s: trailing) { System.out.print(s + " "); } System.out.println(); } public static void main(String[] args) { f(1, "one"); f(2, "two", "three"); f(0); } } ~~~ 輸出: ~~~ required: 1 one required: 2 two three required: 0 ~~~ 這段程序展示了如何使用除了**Object**類之外類型的可變參數列表。這里,所有的可變參數都是**String**對象。可變參數列表中可以使用任何類型的參數,包括基本類型。下面例子展示了可變參數列表變為數組的情形,并且如果列表中沒有任何元素,那么轉變為大小為 0 的數組: ~~~ // housekeeping/VarargType.java public class VarargType { static void f(Character... args) { System.out.print(args.getClass()); System.out.println(" length " + args.length); } static void g(int... args) { System.out.print(args.getClass()); System.out.println(" length " + args.length) } public static void main(String[] args) { f('a'); f(); g(1); g(); System.out.println("int[]: "+ new int[0].getClass()); } } ~~~ 輸出: ~~~ class [Ljava.lang.Character; length 1 class [Ljava.lang.Character; length 0 class [I length 1 class [I length 0 int[]: class [I ~~~ `getClass()`方法屬于 Object 類,將在"類型信息"一章中全面介紹。它會產生對象的類,并在打印該類時,看到表示該類類型的編碼字符串。前導的**\[**代表這是一個后面緊隨的類型的數組,**I**表示基本類型**int**;為了進行雙重檢查,我在最后一行創建了一個**int**數組,打印了其類型。這樣也驗證了使用可變參數列表不依賴于自動裝箱,而使用的是基本類型。 然而,可變參數列表與自動裝箱可以和諧共處,如下: ~~~ // housekeeping/AutoboxingVarargs.java public class AutoboxingVarargs { public static void f(Integer... args) { for (Integer i: args) { System.out.print(i + " "); } System.out.println(); } public static void main(String[] args) { f(1, 2); f(4, 5, 6, 7, 8, 9); f(10, 11, 12); } } ~~~ 輸出: ~~~ 1 2 4 5 6 7 8 9 10 11 12 ~~~ 注意嗎,你可以在單個參數列表中將類型混合在一起,自動裝箱機制會有選擇地把**int**類型的參數提升為**Integer**。 可變參數列表使得方法重載更加復雜了,盡管乍看之下似乎足夠安全: ~~~ // housekeeping/OverloadingVarargs.java public class OverloadingVarargs { static void f(Character... args) { System.out.print("first"); for (Character c: args) { System.out.print(" " + c); } System.out.println(); } static void f(Integer... args) { System.out.print("second"); for (Integer i: args) { System.out.print(" " + i); } System.out.println(); } static void f(Long... args) { System.out.println("third"); } public static void main(String[] args) { f('a', 'b', 'c'); f(1); f(2, 1); f(0); f(0L); //- f(); // Won's compile -- ambiguous } } ~~~ 輸出: ~~~ first a b c second 1 second 2 1 second 0 third ~~~ 在每種情況下,編譯器都會使用自動裝箱來匹配重載的方法,然后調用最明確匹配的方法。 但是如果調用不含參數的`f()`,編譯器就無法知道應該調用哪個方法了。盡管這個錯誤可以弄清楚,但是它可能會使客戶端程序員感到意外。 你可能會通過在某個方法中增加一個非可變參數解決這個問題: ~~~ // housekeeping/OverloadingVarargs2.java // {WillNotCompile} public class OverloadingVarargs2 { static void f(float i, Character... args) { System.out.println("first"); } static void f(Character... args) { System.out.println("second"); } public static void main(String[] args) { f(1, 'a'); f('a', 'b'); } } ~~~ **{WillNotCompile}**注釋把該文件排除在了本書的 Gradle 構建之外。如果你手動編譯它,會得到下面的錯誤信息: ~~~ OverloadingVarargs2.java:14:error:reference to f is ambiguous f('a', 'b'); \^ both method f(float, Character...) in OverloadingVarargs2 and method f(Character...) in OverloadingVarargs2 match 1 error ~~~ 如果你給這兩個方法都添加一個非可變參數,就可以解決問題了: ~~~ // housekeeping/OverloadingVarargs3 public class OverloadingVarargs3 { static void f(float i, Character... args) { System.out.println("first"); } static void f(char c, Character... args) { System.out.println("second"); } public static void main(String[] args) { f(1, 'a'); f('a', 'b'); } } ~~~ 輸出: ~~~ first second ~~~ 你應該總是在重載方法的一個版本上使用可變參數列表,或者壓根不用它。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看