Java 基础教程

Java 流程控制

Java 数组

Java 面向对象(I)

Java 面向对象(II)

Java 面向对象(III)

Java 异常处理

Java 列表(List)

Java Queue(队列)

Java Map集合

Java Set集合

Java 输入输出(I/O)

Java Reader/Writer

Java 其他主题

Java 可变参数(Varargs)

在本文中,您将借助示例来学习Java中的可变参数(Varargs)。您还将学习何时使用varargs,何时不使用它们。

Java中的varargs是什么?

假设您正在创建Java方法。但是,您不确定您的方法将接受多少个参数。为了解决这个问题,Java 1.5引入了varargs。

Varargs是变量参数的缩写。 在Java中,方法的参数可以接受任意数量的值。 可以接受可变数量的值的该参数称为varargs。

实现 varargs 的语法如下:

accessModifier methodName(datatype… arg) {
    // 方法主体
}

为了定义vararg,在方法的形参中使用……(三个点)。

接受可变数量参数的方法称为可变数量方法,或简称为varargs方法。

首先,让我们看一下不使用varargs的示例:

class NoVararg {

    public int sumNumber(int a, int b){
        return a+b;
    }

    public int sumNumber(int a, int b, int c){
        return a+b+c;
    }

    public static void main( String[] args ) {
        NoVararg obj = new NoVararg();
        System.out.println(obj.sumNumber(1, 2));
        System.out.println(obj.sumNumber(1, 2, 3));
    }
}

当您运行该程序时,输出将是:

3
6

正如您看到的,必须重载sumNumber()方法才能使其适用于3个参数。

如果用户要添加5个数字或10或100,该怎么办?

使用varargs可以以一种简洁的方式处理这一问题。让我们看一个代码示例:

示例:可变参数的工作演示

class VarargExample {

    public int sumNumber(int ... args){
        System.out.println("参数长度: " + args.length);
        int sum = 0;
        for(int x: args){
            sum += x;
        }
        return sum;
    }

    public static void main( String[] args ) {
        VarargExample ex = new VarargExample();

        int sum2 = ex.sumNumber(2, 4);
        System.out.println("sum2 = " + sum2);

        int sum3 = ex.sumNumber(1, 3, 5);
        System.out.println("sum3 = " + sum3);

        int sum4 = ex.sumNumber(1, 3, 5, 7);
        System.out.println("sum4 = " + sum4);
    }
}

运行该程序时,输出为:

参数长度: 2
sum2 = 6
参数长度: 3
sum3 = 9
参数长度: 4
sum4 = 16

在这里,sumNumber()方法返回传递给它的int参数的总和(与传递的参数数量无关)。

正如您看到的,varargs在某些情况下非常有用。但是,如果您确定传递给方法的参数数量,请改用方法重载。例如,如果您确定sumNumber()方法仅用于计算2个或3个参数的总和,请像第一个示例一样使用重载。

让我们再举一个实例。Java库中定义的format()方法接受varargs。在JDK中,format()方法定义如下:

public static String format(Locale l, String format, Object... args) {
    // body
}

示例:format()方法

class Company {
    public static void main(String[] args) {
        String siteName = "(niaoge.com)";
        int empCount = 6;
        String type = "教程网站";
        System.out.println(
                String.format(
                        "Site Name : %s, Emp Count: %d Type: %s",
                        siteName, empCount, type
                )
        );
    }
}

运行该程序时,输出为:

Site Name : (niaoge.com), Emp Count: 6 Type: 教程网站

可变参数在后台如何工作?

让我们看以下伪代码:

public int sumNumber(int ... nums) {
    // 方法主体
}

... 语法告诉Java编译器可以使用零个或多个参数来调用该方法。 结果,nums变量被隐式声明为int []类型的数组。 因此,在方法内部,使用数组语法访问nums变量。

如果没有参数,则长度nums为0。

重载 Varargs 方法

与典型方法类似,您可以重载vararg方法。

示例:Varargs方法重载

class VarargOverload {

    private void test(int ... args){
        int sum = 0;
        for (int i: args) {
            sum += i;
        }
        System.out.println("sum = " + sum);
    }

    private void test(boolean p, String ... args){
        boolean negate = !p;
        System.out.println("negate = " + negate);
        System.out.println("args.length = "+ args.length);
    }

    public static void main( String[] args ) {
        VarargOverload obj = new VarargOverload();
        obj.test(1, 2, 3);
        obj.test(true, "hello", "world");
    }
}

运行该程序时,输出为:

sum = 6
negate = false
args.length = 2

在上面的程序中,test()方法通过更改其接受的参数数量而重载。

使用 Varargs 时要记住的事情

这是使用Java Varargs时应记住的几件事:

1.在定义方法签名时,请务必保留最后varargs。

变量参数必须是传递给方法的最后一个参数。考虑一下,您调用了如下doSomething()方法:

doSomething(1, 2, 3, 4);

并且,您的doSomething()方法定义为:

//错误的方法声明
public void doSomething(int ... nums, int p){
    // method body
}

在这种情况下,编译器无法确定传递给nums的参数数量。

但是,如果将方法定义为:

public void doSomething(int p, int ... nums) {
    // method body
}

Java编译器将第一个参数分配给 p,其余int参数分配给 nums。

2.一种方法只能有一个varargs参数。

例如,此方法声明不正确:

int doSomething(int p, float ... floatNums, double ... doubleNums) {
    // code
}

Varargs方法重载中的歧义

让我们看一下这样的重载test()方法:

class Demo { 
  
    static void test(int ... vargs) {
        // method body
    }
    
    static void test(int n, int ... vargs) {
        // method body
    }
}

在上面的程序中,即使您尝试调用test()方法,即使test()方法已重载并且接受不同数量的参数,编译器也会感到困惑。

编译器不知道调用哪个方法。编译器可能会认为,您正在尝试test(int ... vargs)使用一个varargs参数进行调用。同样,编译器可能会认为,您正在尝试test(int n, int ... vargs)使用传递给第一个参数的参数调用,而第二个参数为空。

由于存在两种可能性,因此会引起歧义。因此,有时您可能需要使用两个不同的方法名称,而不是重载varargs方法。