第5章(4) 可变参数列表

当调用方法时,方法的参数个数或类型未知时,称其为可变参数列表。可以使用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');
       }
}

 

上一篇:第5章(3) 初始化


下一篇:第4章 控制执行流程