Java基礎:五、可變參數列表 (9)

  • 2020 年 3 月 17 日
  • 筆記

由於所有的類都直接或間接繼承於Object類,所以可以創建以Object數組為參數方法,以此獲取可變參數列表

//  JavaSE5之前  class A{}  public class VarArgs{    static void printArray(Object[] args){        for(Object obj : args){          System.out.println(obj + "");      }      System.out.println();    }    public static void main(String[] args){        printArray(new Object[]{new Integer(47),new Float(3.14),new Double(11.11)});        printArray(new Object[]{"one","two","three"});        printArray(new Object[]{new A(),new A(),new A()});    }  }
// JavaSE5增加的新特性,可以使用它們來定義可變參數列表    class A{}  public class NewVarArgs{    static void printArray(Object... args){        for(Object obj : args){          System.out.println(obj + "");      }      System.out.println();    }    public static void main(String[] args){        printArray(new Integer(47),new Float(3.14),new Double(11.11));        printArray("one","two","three");        printArray(new A(),new A(),new A());        printArray((Object [])new Integer[]{1,2,3,4,5});        printArray(); // Empty list is ok    }  }

有了可變參數,就再也不用顯式地編寫數組語法了,當你指定參數時,編譯器實際上會為你去填充數組。此時仍舊是一個數組。但是,這不僅僅只是從元素列表到數組的自動轉換,printArray((Object [])new Integer[]{1,2,3,4,5});中Integer數組(通過使用自動包裝而創建的)被轉型為一個Object數組,並且傳遞給printArray(),此時,它已經是個數組了,所以不會在其上執行任何轉換。因此,如果有一組事物,可以把它們當作列表傳遞,而若果你已經有了一個數組,該方法可以把它們當作可變參數列表來接受

** 傳遞0個參數**

public class OptionalTrailingArguments{      static void f(int required,String... trailing){ // 可變參數列表可以使用任何類型的參數,包括基本類型          System.out.println("required: " + required + " ");          for(String s : trailing){              System.out.println(s + " ");        }        System.out.println();    }        public static void main(String[] args){          f(1,"one");          f(2,"two","three");          f(1);      }  }

可變參數列表可以使用除Object之外類型的任何類型的參數,包括基本類型。

public class VarargType{      static void f(Character... args){           System.out.print(args.getClass);           System.out.println(" length " + args.length);      }        static void f(int... args){           System.out.print(args.getClass);           System.out.println(" length " + args.length);      }        public static void main(String[] args){          f('a');          f(); // 如果在列表中沒有任何元素,那麼轉變成的數據的尺寸為0          g(1);          g();          System.out.println("int[]: " + new int[0].getClass());      }  }

getClass()方法屬於Object的一部分,它將產生對象的類,並且在列印該類時,可以看到表示該類類型的編碼的字元串。前面的"[" 表示這是一個後面緊隨的類型的數組,而緊隨的「I」表示類型為int。這樣也驗證了使用可變參數列表不依賴自動包裝i 只,而實際上使用的是基本類型

public class AutoboxingVarargs{      public static void f(Integer... args){           for(Integer s : args){              System.out.print(i + " ");        }        System.out.println();      }        public static void main(String[] args){          f(new Integer(1),new Integer(2));          f(4,5,6,7,8,9);          f(10,new Integer(11),12);// 可以在單一的參數列表中將類型混合在一起,而自動包裝機制將有選擇地將int參數提升為Integer      }  }

可變參數列表使得重載過程變得複雜了,下面的例子中,編譯器都會使用自動包裝機制來匹配重載的方法,然後調用最明確匹配的方法,但是在不使用參數調用f()時,編譯器就無法直到應該調用哪一個方法了。可以給所有方法增加一個非可變參數,但是建議的是 只在重載方法的一個版本上使用可變參數列表,或者壓根不用它

public class OverloadingVarargs{      static void f(Character... args){            for(Character c : args){              System.out.print(c + " ");            }            System.out.println();      }        static void f(Integer... args){            for(Integer c : 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(); // 無法調用      }  }