形式参数类型声明中 double... 和 double[] 的区别 [英] Difference between double... and double[] in formal parameter type declaration

查看:31
本文介绍了形式参数类型声明中 double... 和 double[] 的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have question: what is the difference between these two declarations?

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

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

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

推荐答案

On varargs

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

On varargs

The Type... construct in method parameter declaration is commonly what is called varargs. In JLS, it's called the variable arity parameter.

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

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

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

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 允许你做的:

To illustrate in code, this is what varargs allows you to do:

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

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

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

In contrast, without the varargs construct, you must do this:

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

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

varargs 就是所谓的语法糖,它可以隐藏冗长的内容.

The varargs is what is called a syntactic sugar that hides the verbosity from you.

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

So to go back to your question, the difference between printMax(double... numbers) and printmax(double numbers[]) is that the first is a variable arity method, meaning you can give it a variable number of parameters. The latter is a fixed arity method, meaning it will accept one and only parameter.

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

Note the quote above about T... being really a T[]. That is, even with varargs, you can still do the following:

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

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

Here you're manually creating the array to hold the vararg parameters. In fact, if you go as far as decompiling the code, you'll find that just as JLS specified, f does in fact take int[] parameter, and f(1, 2, 3) is implemented as f(new int[] { 1, 2, 3 }).

如何解析 varargs 是相当复杂的,有时它会做一些让你感到惊讶的事情.

How varargs are resolved is quite complicated, and sometimes it does things that may surprise you.

考虑这个例子:

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 参数,您可以执行以下任一操作:

Due to how varargs are resolved, the last statement invokes with objs = null, which of course would cause NullPointerException with objs.length. If you want to give one null argument to a varargs parameter, you can do either of the following:

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

相关问题

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

Related questions

The following is a sample of some of the questions people have asked when dealing with varargs:

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

As the previous section showed, varargs can be tricky. Used in the right situations, however, they can lead to much more concise code.

这里引用了 Effective Java 2nd Edition,Item 42:明智地使用可变参数(作者强调):

Here's a quote from Effective Java 2nd Edition, Item 42: Use varargs judiciously (emphasis by author):

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

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 实际上建议为最常见的使用场景提供固定数量的重载.

Not only can varargs be confusing, it can also be costly. Effective Java 2nd Edition actually recommends providing fixed-arity overloads for the most common usage scenarios.

假设您已确定 95% 的方法调用具有三个或更少的参数.然后声明方法的 5 个重载,每个重载 0 到 3 个普通参数,当参数数量超过 3 时使用单个可变参数.

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.

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

The book goes in much greater depth, but essentially you should only use varargs when it actually makes sense. And even in those cases, you may still want to consider providing fixed-arity overloads for performance reasons.

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

Here are some examples where varargs makes sense:

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

Please, please, do not make a habit of declaring arrays like this:

int x[];

你应该用类型代替括号,而不是用标识符:

You should instead put the brackets with the type, rather than with the identifier:

int[] x;

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

Note that this is also how arrays are referred to in the above discussions, e.g. T[] int[], etc.

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆