java - 形参类型声明中 double... 和 double[] 的区别

标签 java arrays variadic-functions parameter-passing

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

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

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

双...数字双数字[]相同吗?

最佳答案

关于可变参数

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

JLS 8.4.1 Format parameters

The last formal parameter in a list is special; it may be a variable arity parameter, indicated by an elipsis following the type.

If the last formal parameter is a variable arity parameter of type T, it is considered to define a formal parameter of type T[]. The method is then a variable arity method. Otherwise, it is a fixed arity method. Invocations of a variable arity method may contain more actual argument expressions than formal parameters. All the actual argument expressions that do not correspond to the formal parameters preceding the variable arity parameter will be evaluated and the results stored into an array that will be passed to the method invocation.

为了在代码中说明,这就是 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(doublenumbers[]) 之间的区别在于,第一个是可变数量方法,这意味着您可以为其提供可变数量的参数。后者是一种固定数量方法,这意味着它将接受一个且唯一的参数。

请注意上面关于 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 })

另请参阅

<小时/>

Varargs 陷阱

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

考虑这个例子:

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!!!

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

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

相关问题

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

<小时/>

何时使用可变参数

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

这里引用了Effective Java 第二版,第 42 条:明智地使用可变参数(作者强调):

The lesson is clear. Don't retrofit every method that has a final array parameter; use varargs only when a call really operates on a variable-length sequence of values.

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

Suppose you've determined that 95 percent of the calls to a method have three or fewer parameters. Then declare five overloadings of the method, one for each with zero through three ordinary parameters, and a single varargs for use when the number of parameters exceed three.

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

相关问题

API 链接

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

<小时/>

关于数组声明

拜托,拜托,不要养成像这样声明数组的习惯:

int x[];

您应该将括号与类型放在一起,而不是与标识符一起放入:

int[] x;

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

相关问题

关于java - 形参类型声明中 double... 和 double[] 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2888305/

相关文章:

java - JAXB 和包含泛型的集合

java - 如何在 Minecraft 1.10 上编写速度破解代码?

java - 头文件的优点/缺点

c++ - 如何将可变数量的参数传递给 printf/sprintf

java - 使用正则表达式仅允许左对齐零

javascript - 如何使具有 map 功能的 3 列网格使用react

java - 如何调用ArrayList中的每个数组并按年龄对ArrayList进行排序?

java - 替换字符串数组中的特定字符串

java - 使用Varargs调用方法时出现javassist.CannotCompileException

java - java 中的可变参数和泛型