当调用方法时,方法的参数个数或类型未知时,称其为可变参数列表。可以使用Object数组来实现这样的功能。因为,所有的类都是直接或间接继承于Object类。
1. 在没有可变参数列表的时候,是用数组实现类似的功能,看下面的例子:
class A1{} 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[]{ new Integer(47),new Float(3.14),new Double(11.11) }); printArray(new Object[]{"one","two","three"}); printArray(new Object[]{new A1(),new A1(),new A1()}); } }
toString()方法的默认行为是,打印类的名字和对象的地址。
2. 有了可变参数列表,就再也不用显式地编写数组语法了,当你指定参数时,编译器实际上会为你去填充数组。参数获取的仍然是一个数组。如果你有一组事务,可以当做列表传递,而对于数组,其依旧当作可变参数列表来接受。
如下面的代码:
class A{} 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){ printArray(new Integer(47),new Float(3.14),new Double(11.11)); printArray(47, printArray("one","two","three"); printArray(new A(),new A(),new A()); printArray((Object[])new Integer[]{1,2,3,4}); printArray(); } }
3. 可变参数列表也可以使用Object以外的类型,但是传入参数为其他类型时,就会抛出异常。
public class Test { public static void printArray(Book... books) { for (int i = 0; i < books.length; i++) { System.out.println(books[i]); } } public static void main(String[] args) { // printArray(1);//抛异常 printArray(new Book()); } } class Book { }
4. 可变参数列表中基本类型和非基本类型可以同时使用:
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(new Integer(1),new Integer(2)); f(3,4,5,6,7,8,9); f(10,new Integer(11),12); } }
5. 重载
编译器会根据参数类型匹配最明确的方法,但可变参数列表仍然是重载变得不安全。
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.print("third "); for(Long l:args) System.out.print(l+" "); System.out.println(); } static void f(Double...args){ System.out.print("forth "); for(Double d:args) System.out.print(d+" "); System.out.println(); } public static void main(String[] args){ f('a','b','c'); f(1); f(2,1); f(0.1); f(0L); } }
上面的例子得到了正确的匹配,但对语句f(),编译器就懵逼了。
我们可能想过在某一个方法中增加一个非可变参数来解决该问题,但这是不被允许的:
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');//Error } }
如果给两个方法都添加一个非可变参数,问题就解决了。即重载的方法必须保持一致的参数形式!
public class OverloadingVarargs2 { 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'); } }