在Java中,如果你明确地初始化一个对象数组,包含"new Object[]"和不包含它是否不同?

10
前言:这个问题已经在这里被问过,但我特别想知道作者具体的意思。
我正在阅读《Java编程思想》第三版修订版4.0中的第4章“初始化和清理”部分,Eckel在其中展示了以下代码段:
public class ArrayInit
{
  public static void main(String[] args)
  {
    Integer[] a =
    {
      new Integer(1),
      new Integer(2),
      new Integer(3),
    };

    Integer[] b = new Integer[]
    {
      new Integer(1),
      new Integer(2),
      new Integer(3),
    };
  }
}

并表示如下:

第一种形式有时很有用,但它更受限,因为数组的大小在编译时确定。
第二种形式提供了一种方便的语法,用于创建和调用可以产生与C语言中的可变参数列表(称为“varargs”)相同效果的方法。这些方法可以包括未知数量的参数以及未知类型。

在我看来,我从未听说过Eckel所描述的两者有所不同。据我理解,它们都是静态大小的数组。我不明白第一种方式比第二种方式更加“有限”的原因在哪里。

他在说什么?


2
我不知道他在说什么;这些是完全等价的。 - Louis Wasserman
2
你要么引用了错误的上下文,要么他不知道自己在说什么。(我觉得两种情况的概率各占50%。) - Hot Licks
2
我认为这是他的书上的错误 Jon Skeet知道发生了什么 - gtgaxiola
1
他所说的“第二种形式”是否可能指的是像Integer[] nums = new Integer[n];这样的表达式,其中n是运行时表达式?我无法理解“C语言的可变参数列表”是什么意思,因为Java也支持这个功能,只不过更方便和安全(并且与此无关,以我个人看来)。 - 5gon12eder
2
我刚刚检查了第四版 - 现在文本在上面引用的示例之后说:“虽然第一种形式很有用,但它更受限制,因为它只能在定义数组的点使用。您可以在任何地方使用第二和第三种形式,甚至在方法调用内部。例如,您可以创建一个String对象数组以传递给另一个方法的main(),以提供替代命令行参数:”。 - Tirath
显示剩余5条评论
3个回答

4

我认为这可能是作者所指的。

自从Java 5以来,我们可以使用可变参数列表声明函数。

public static int newStyleSum(final int... numbers) {
    int sum = 0;
    for (final int number : numbers) {
        sum += number;
    }
    return sum;
}

它们可以像这样使用:

int s = newStyleSum(1, 2, 3, 4);

这个功能只是一种语法糖。 内部,一个匿名数组被传递到函数中。

在拥有此语法之前,上面的示例必须编写为:

public static int oldStyleSum(final int[] numbers) {
    int sum = 0;
    for (int i = 0; i < numbers.length; ++i) {
        sum += numbers[i];
    }
    return sum;
}

并且被称为
int s = oldStyleSum(new int[]{1, 2, 3, 4});  // "second" form

但不是

int s = oldStyleSum({1, 2, 3, 4});  // "first" form (syntax error)

即使在今天,这仍然是一个语法错误。

而且这可能确实是他所说的内容。Java 5发布于2004年,因此对于一本2002年的书来说是有道理的。

新的语法更加灵活 - 更重要的是 - 具有向后兼容性,因此我们仍然可以做到

int s = newStyleSum(new int[]{1, 2, 3, 4});

或者,更为重要的是,
int[] numbers = {1, 2, 3, 4};
int s = newStyleSum(numbers);

如果我们想要的话。

2

看起来他是指数组初始化程序,特别是new Integer[]。从同一章节中可以找到使用显式初始化程序的示例。

Other.main(new String[]{ "fiddle", "de", "dum" }); 

展示将数组传递给方法的有用性,这是没有数组初始化表达式就无法实现的。

1

你说得对,这没有任何意义。

这里是第2版使用的内容

有时这很有用,但它更加受限,因为数组的大小在编译时确定。初始化器列表中的最后一个逗号是可选的。(此功能使长列表的维护更容易。)

这里的“这”指的是“使用花括号括起来的列表初始化对象数组”,这是正确的。看起来有人做了一个错误的编辑,认为“这”指的是“第一种形式”。

它继续说第二种形式是模拟varargs的有用方式,当时是真的,但Java现在已经获得了实际的varargs。(第一种形式只能在数组声明中使用,不能在方法调用中使用,因此对于varargs没有用处)。


我正在阅读版本4.0,并且我在问题中提出的文本是从那里复制的。不过你说的有道理。 - Taylor Lopez
@iAmMortos 啊,我没注意到。是的,只是一个不好的编辑。 - that other guy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接