天天看点

学习笔记-可变参数基本用法:使用要求:与一般T[]数组参数类型的区别

基本用法:

public class VarargsLearn {
    public static void inputVarargs(String... args){
        //可变参数方法
        String[] a = args;
    }    
    public static void main(String[] args) {        
        inputVarargs("a","2","4");
        String[] inputArray = new String[]{"a","2","4"};
        inputVarargs(inputArray);
    }
}
           

使用要求:

Java语言规范有如下表述:

  1. 方法或构造函数的形参(如果有的话)是通过逗号分隔的参数制定的列表指定的。列表的最后一个形参是特殊的,可以是一个可变元数参数,通过类型后面的省略号来表示。
  2. 如果最后一个形参是类型为T的可变参数,则将其视作定义了一个T[]类型的形参。
  3. 可变参数方法的调用可以包含比形参更多的实参表达式。对于和可变参数之前的形参不对应的所有表达式,将会对其进行求值,并把结果存储在将传递给方法调用的数组中。

第二点中说明,实际上编译器认为创建了一个T[]类型的形参;

//编译器提示方法已经存在
    public static void inputVarargs(String... args){
        //可变参数方法
        String[] a = args;
    }  
    public static void inputVarargs(String[] args){
        //数组参数方法
        String[] a = args;
    }  
           

第三点下面举例说明:

String[] inputArray = new String[]{"a","2","4"};
        inputVarargs();
        inputVarargs("a","2","4");
        inputVarargs(inputArray);

        //反编译class代码如下,如果实参就是对应类型的数组,编译器不做处理;如果不是构造对应的类型的数组。
        String[] inputArray = new String[]{"a", "2", "4"};
        inputVarargs(new String[]);
        inputVarargs(new String[]{"a", "2", "4"});
        inputVarargs(inputArray);
           

java中数组也是一个对象,当出现一个object类型的可变参数时,需要注意编译器对代码做了怎样的处理,举例说明:

public static void inputObjectVarargs(Object... args){
    }
    public static void main(String[] args) {
        String[] inputArray = new String[]{"a","2","4"};
        //错误用法
        //inputVarargs("a","2","4",args);

        //object类型的可变参数
        inputObjectVarargs("a","2","4");
        inputObjectVarargs("a","2","4",inputArray);
        inputObjectVarargs(inputArray);
        inputObjectVarargs(new Object[]{inputArray});
    }

        //反编译class,代码如下
        //将实参包装为object[]
        inputObjectVarargs(new Object[]{"a", "2", "4"});
        inputObjectVarargs(new Object[]{"a", "2", "4", inputArray});
        //认为是object[]数组直接传入,入参是一个长度为3的string[]
        inputObjectVarargs(inputArray);
        //认为是object[]数组直接传入,入参是一个长度为1的object[],该数组中的元素是inputArray这个数组
        inputObjectVarargs(new Object[]{inputArray});
           

与一般T[]数组参数类型的区别

如果没有可变参数,也可以通过数组参数类型的参数做到同样的事情。是否可变参数只存在java层面?

public static void inputVarargs(String... args){
        String[] a = args;
    }
    public static void inputArrayArg(String[] args){
        String[] a = args;
    }
    //反编译代码,可以看到class中仍然能识别出数组参数和可变参数
    public static void inputVarargs(String... args) {
    }
    public static void inputArrayArg(String[] args) {
    }
    //使用idea查看两个方法字节码区别
    public static transient varargs inputVarargs([Ljava/lang/String;)V
    public static inputArrayArg([Ljava/lang/String;)V
    //class中通过transient varargs标记一个方法是否是可变参数方法
    //而两个方法的入参都是[Ljava/lang/String;即:string[]。
    //解释了“将其视作定义了一个T[]类型的形参”、可变参数和相同类型数组方法提示方法已存在的问题