非声明中的数组初始化语法

149
我可以写:
AClass[] array = {object1, object2}

我也可以写成:

AClass[] array = new AClass[2];
...
array[0] = object1;
array[1] = object2;

但我无法编写:

AClass[] array;
...
array = {object1, object2};

为什么Java会阻塞这个?

我知道如何绕过它,但有时候简单一些会更好。

例如:

public void selectedPointsToMove(cpVect coord) {

    if (tab == null) {
        if (arePointsClose(coord, point1, 10)) {
            cpVect[] tempTab = {point1};
            tab = tempTab;
        } else if (arePointsClose(point2, coord, 10)) {
            cpVect[] tempTab = {point2};
            tab = tempTab;
        } else {
            cpVect[] tempTab = {point1,point2};
            tab = tempTab;
        }
    }
}

自从我学会在Java中使用数组以来,这个简单的问题一直困扰着我。

4个回答

143
为什么 Java 要这么限制呢?可能是由于某些微妙的语法原因。需要注意的是,一些数组创建和初始化构造不在 Java 1.0 中,(如果我没记错的话)它们是在 Java 1.1 中添加的。
但是,“为什么”并不重要......限制是存在的,你必须接受它。
我知道如何解决它,但有时更简单的方法会更好。
您可以编写以下内容:
AClass[] array;
...
array = new AClass[]{object1, object2};

9
如果没有这个新声明,代码中的语句块和数组初始化器就没有区别(就像JavaScript中一样,这可能会引起误解)。 - bestsss
10
如果{o1()}是一个有效的表达式,而{o1();}是一个有效的语句块,那么会让人感到困惑,并且很难分析。解析器必须先读取到' } '或'; ',然后才能区分这两种情况。这个语法问题一点也不微妙! - Stephen C

20

我会尝试回答为什么的问题:Java数组相对于像ArrayList这样更具动态性的类而言非常简单和原始。Java希望在声明时知道应为数组分配多少内存。ArrayList更加动态,其大小可以随时间变化而变化。

如果您使用两个长度来初始化数组,后来发现需要三个长度,那么您必须放弃已有的内容并创建一个全新的数组。因此出现了“new”关键字。

在您的前两个示例中,您在声明时告诉内存要分配多少。在第三个示例中,数组名称成为指向完全无内容的指针,因此,在初始化时,您必须显式地创建一个新数组以分配正确数量的内存。

我认为(如果有人知道得更好,请纠正我)第一个示例

AClass[] array = {object1, object2}

实际上意味着

AClass[] array = new AClass[]{object1, object2};

但是Java设计人员所做的是,如果您在声明时创建数组,那么可以更快地编写它。

建议的解决方法很好。如果运行时时间或内存使用量很重要,请使用数组。如果不重要,并且您想要更容易理解和使用的代码,请使用ArrayList。


3
如你所说,这是一个快捷方式。引用Oracle的话:“或者,您可以使用快捷语法来创建和初始化数组”。可能的原因是必须在某个时刻使用new为数组在内存中分配空间。在声明中,快捷方式隐式地包含了new,但是此快捷方式仅在声明中有效。在其他地方,不能使用快捷方式,必须使用new。 - mins
4
很抱歉,但你对“为什么”问题的回答并不站得住脚。编译器可以通过计算在 {} 之间的表达式数量来确定数组需要多大,就像它对允许的初始化形式一样。 - Stephen C

8

我无法回答为什么的部分。

但是如果您想要一些动态的东西,那么为什么不考虑使用集合ArrayList呢。

ArrayList可以是任何对象类型。

如果您非要将其作为一个数组使用,可以在其上使用toArray()方法。

例如:

            ArrayList<String> al = new ArrayList<String>();
            al.add("one");
            al.add("two");
            String[] strArray = (String[]) al.toArray(new String[0]);

今日免费次数已满, 请开通会员/明日再来

3
不需要将数组的返回类型强制转换为String[]。根据契约,返回的数组与指定的数组类型相同。http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html#toArray(T[]) - Ankur Agarwal

4

如果您不喜欢这种笨重的 new AClass[] { ... } 语法,那么这里有一些简化方法:

public AClass[] c(AClass... arr) { return arr; }

请随意使用这个小函数:
AClass[] array;
...
array = c(object1, object2);

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