当前位置: 首页 > 面试题库 >

形式参数类型声明中double…和double []之间的区别

范霄
2023-03-14
问题内容

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

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

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

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


问题答案:

在可变参数上

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

JLS8.4.1格式参数

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

如果最后一个形式参数是类型的可变arity参数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[]。也就是说,即使使用了varargs,您仍然可以执行以下操作:

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

在这里,您正在手动创建数组以容纳vararg参数。实际上,如果深入研究代码,您会发现,正如JLS指定的f那样,实际上确实带有int[]参数,并且f(1, 2, 3)实现为f(new int[] { 1, 2, 3 })

也可以看看

  • Java语言指南/ varargs

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。如果要将一个null参数赋给varargs参数,则可以执行以下任一操作:

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

关于何时使用varargs

如上一节所示,可变参数可能很棘手。但是,如果在正确的情况下使用它们,它们可以导致更简洁的代码。

这是来自 有效Java第二版,项目42:明智地使用varargs 的引文(作者强调):

这课很清楚。 不要改造所有带有最终数组参数的方法; 在调用确实对可变长度的值序列进行运算 时才 使用varargs

varargs不仅会造成混乱,而且成本很高。 实际上,Effective Java 2nd Edition 建议为最常见的使用情况提供固定数量的重载。

假设您确定95%的方法调用具有三个或更少的参数。然后声明该方法的5个重载,每个重载为0到3个普通参数,并在参数数量超过3个时使用单个varargs。

这本书的内容更深入,但是从本质上讲,只有在真正有意义时才应使用varargs。即使在这些情况下,出于性能原因,您可能仍要考虑提供固定的arar重载。

API链接

以下是varargs有意义的一些示例:

  • java.util.Arrays.asList(T...)
  • java.util.PrintStream.printf(String format, Object... args)
  • java.lang.reflect.Method.invoke(Object obj, Object... args)

关于数组声明

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

int x[];

相反,您应该将括号放在 type 而不是 标识符上

int[] x;

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

相关问题

  • 有什么区别Object[] xObject x[]
  • int[] myArrayint myArray[]Java 之间的区别
  • 在数组声明int[] k,iint k[],i
    • 这些声明导致i!的类型不同。


 类似资料:
  • 问题内容: 我进行了一个junit测试,使用以下命令声明了两个Double对象: 很好,然后我决定将其更改为使用原始double,除非您也提供了增量,否则该结果被弃用了。 所以我想知道在assertEquals中使用Double对象还是原始类型有什么区别?为什么不使用不带增量的对象,但不推荐使用不带增量的基元呢?Java是否在后台执行了已经考虑了默认增量值的操作? 谢谢。 问题答案: 没有断言方法

  • 问题内容: 和之间有什么区别? 问题答案: 是一个对象,并且是原始数据类型。 有关更多详细信息,请参见此答案。 Double类将原始类型double的值包装在对象中。类型为Double的对象包含单个类型为double的字段。 来源:http : //docs.oracle.com/javase/7/docs/api/java/lang/Double.html

  • 问题内容: 我很好奇为什么必须这样声明float文字: 代替 为什么默认类型是双精度类型,为什么编译器不能通过查看赋值的左侧来推断它是浮点型的?Google仅提供关于默认值的解释,而不是为什么如此。 问题答案: 为什么默认类型是双精度型? Java语言的设计者最好问这个问题。他们是唯一知道做出语言设计决定的 真正 原因的人。但我希望推理遵循以下几条原则: 他们需要区分两种类型的文字,因为从数学的角

  • 问题内容: float数据类型是单精度32位IEEE 754浮点,double数据类型是双精度64位IEEE 754浮点。 这是什么意思?我什么时候应该使用float而不是double? 问题答案: 总结一下: float用32位表示,带有1个符号位,8位指数和23位有效数(或从科学记号中得出的结果:2.33728 * 10 12; 33728为有效数)。 double 用64位表示,带有1个符号

  • float数据类型是单精度32位IEEE 754浮点,而double数据类型是双精度64位IEEE 754浮点。 这是什么意思?什么时候应该使用float而不是double或者相反呢?

  • 问题内容: 我知道这是一个包装类,它包装数字。今天,我看到了另一个主要区别: 我真奇怪! 因此,如果每次使用,我们都必须执行以下操作: 我无法解释为什么Double直接将比较做错了。请为我解释。 问题答案: 而在技术上两个不同的对象和运营商只比较引用。 更好,因为它比较值而不是引用。但是仍然不理想。直接比较浮点值应始终将一些误差(ε)考虑在内()。 注意: 这里的比较会产生,但是比较复杂(内部缓存