2

我有一个问题:这两个声明有什么区别?

 public static void printMax(double... numbers) { ... }

 public static void printmax(double numbers[])  { ... }

double... numbers一样的double numbers[]吗?

4

3 回答 3

8

在可变参数上

方法参数声明中的Type...构造通常称为可变参数。在 JLS 中,它被称为可变参数。

JLS 8.4.1 格式参数

列表中的最后一个形参是特殊的;它可能是一个可变的参数,由类型后面的省略号表示。

如果最后一个形参是类型的可变参数T,则认为定义了一个类型的形参T[]。该方法然后是可变的arity方法。否则,它是一种固定数量的方法。变量 arity 方法的调用可能包含比形式参数更多的实际参数表达式。所有与变量 arity 参数之前的形式参数不对应的实际参数表达式都将被计算,并将结果存储到一个数组中,该数组将传递给方法调用。

为了在代码中进行说明,这是 varargs 允许您执行的操作:

static void f(int... nums) {
    for (int num : nums) {
        System.out.println(num);
    }
}
//...

f(1,2,3); // prints "1", "2", "3"

相反,如果没有 varargs 构造,您必须这样做:

static void g(int[] nums) {
    for (int num : nums) {
        System.out.println(num);
    }       
}
//...

g(new int[] { 1, 2, 3 }); // prints "1", "2", "3"

可变参数是所谓的语法糖,它向您隐藏冗长。

所以回到你的问题,和之间的区别在于printMax(double... numbers)printmax(double numbers[])一个是可变的arity方法,这意味着你可以给它可变数量的参数。后者是一种固定数量的方法,这意味着它将接受一个也是唯一的参数。

请注意上面关于T...真正成为T[]. 也就是说,即使使用可变参数,您仍然可以执行以下操作:

f(new int[] { 1, 2, 3 }); // prints "1", "2", "3"

在这里,您手动创建数组来保存可变参数。事实上,如果你对代码进行反编译,你会发现正如 JLS 所指定的f那样,实际上确实接受了int[]参数,并且f(1, 2, 3)实现为f(new int[] { 1, 2, 3 }).

也可以看看


可变参数陷阱

如何解析可变参数是相当复杂的,有时它会做一些让你吃惊的事情。

考虑这个例子:

static void count(Object... objs) {
    System.out.println(objs.length);
}

count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!

由于可变参数的解析方式,最后一条语句调用 with objs = null,这当然会导致NullPointerExceptionwith objs.length。如果您想为nullvarargs 参数提供一个参数,您可以执行以下任一操作:

count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"

相关问题

以下是人们在处理可变参数时提出的一些问题的示例:


关于何时使用可变参数

如上一节所示,可变参数可能很棘手。然而,在正确的情况下使用它们可以产生更简洁的代码。

这是来自Effective Java 2nd Edition,第 42 条:明智地使用 varargs的引述(作者强调):

教训很清楚。不要改造每个具有最终数组参数的方法;当调用真正对可变长度的值序列进行操作时才使用可变参数

可变参数不仅会令人困惑,而且成本也会很高。Effective Java 2nd Edition实际上建议为最常见的使用场景提供固定数量的重载。

假设您已经确定 95% 的方法调用具有三个或更少的参数。然后声明该方法的五个重载,每个重载一个具有零到三个普通参数,一个可变参数用于参数数量超过三个时使用。

这本书更深入,但本质上你应该只在真正有意义的时候使用可变参数。即使在这些情况下,出于性能原因,您可能仍需要考虑提供固定数量的重载。

相关问题

API 链接

以下是可变参数有意义的一些示例:


关于数组声明

请不要养成这样声明数组的习惯:

int x[];

您应该将括号放在type中,而不是在identifier中:

int[] x;

请注意,这也是在上述讨论中引用数组的方式,例如T[] int[]等。

相关问题

于 2010-05-22T18:58:28.007 回答
2

主要区别在于,在第一种情况下,您可以printMax使用多个参数进行调用:

printMax(3.0, 4.0, 5.0)

而在第二种情况下,它只接受一个参数(一个数组double)。

在方法体中,在这两种情况下,数字都将作为数组访问。

double要记住的一件事是,在第一种情况下,即使使用了可变参数表示法,您仍然可以传递单个数组。

于 2010-05-22T13:54:32.223 回答
1

不完全是 - double... 表示变量参数列表 - 此时传递的所有参数都将打包为一个数组。

一个方法中只能有一个可变参数,并且出于显而易见的原因,它必须是其原型中的最后一个。但是,它将在方法中以数组的形式提供,因此在这种特殊情况下没有太大区别。

于 2010-05-22T13:55:27.913 回答