33

顺便说一句,我注意到有人可以编写这样的代码,这很正常:

int arrays[] = {1, 2, 3};
for (int n : arrays)
   System.out.println(n);

但我不明白以下内容是非法的:

for (int n : {1, 2, 3})
   System.out.println(n);

从编译器作者的角度来看,这不会引入任何歧义,不是吗?可以预期数组的类型与先前声明的元素的类型相同。换句话说,n被声明为int,所以数组必须int[]

4

5 回答 5

36

你需要这个语法:

for(int n : new int[]{1, 2, 3})
   System.out.println(n);
于 2013-04-22T05:27:21.597 回答
36

来自 Java 语言规范,§10.6 - Array Initializers

数组初始值设定项以逗号分隔的表达式列表形式编写,用大括号 { 和 } 括起来。

尾随逗号可能出现在数组初始值设定项中的最后一个表达式之后并被忽略。

每个变量初始化器必须与数组的组件类型赋值兼容(第 5.2 节),否则会发生编译时错误。

如果正在初始化的数组的组件类型不可具体化(第 4.7 节),则会出现编译时错误。

数组初始化器是数组创建表达式的一部分,它确实定义了您需要以下四种形式之一才能成功初始化数组:

ArrayCreationExpression:
    new PrimitiveType DimExprs Dimsopt
    new ClassOrInterfaceType DimExprs Dimsopt
    new PrimitiveType Dims ArrayInitializer 
    new ClassOrInterfaceType Dims ArrayInitializer

再次,从规格:

如果 ClassOrInterfaceType 不表示可具体化类型(第 4.7 节),则为编译时错误。否则,ClassOrInterfaceType 可以命名任何命名的引用类型,甚至是抽象类类型(§8.1.1.1)或接口类型(§9)。

这就是您需要语法的原因new int[] {1, 2, 3}

编辑:要更多地了解您的问题的细微差别:

从编译器作者的角度来看,这不会引入任何歧义,不是吗?可以预期数组的类型与先前声明的元素的类型相同。换句话说,n被声明为int,所以数组必须是int[]

,有歧义。 例如,以下两个语句有什么区别?

int[] arr1 = new int[] {1, 2, 3};
short[] arr2 = new short[] {1, 2, 3};

主要区别在于它们在字节码中编译成的内容。一个明显是int,另一个明显是short。但是,如果无法判断哪种数据类型是哪种(数组中的值不超过Short.MAX_VALUE),就不可能断言这个数组毫无疑问是一个int. 回想一下 ashort属于 a 的范围int,因此在使用它时您很容易陷入一些棘手/奇怪的场景。

它变得更有趣: 这是有效的代码。

for(int i : arr2) {
    System.out.println(i);
}

同样,只要arr2不超过中的元素Short.MAX_VALUE,您就可以摆脱和之间的这种模棱两可的short引用int

这是编译器不能仅仅推断出你的意思的另一个原因int。你的意思可能short是.*

*:没有多少人会这样做,但那只是以防万一。

于 2013-04-22T05:33:47.093 回答
7

因为数组是对象,必须实例化。Java 不将 {} 本身识别为数组。但是,它确实允许您使用代码块(即 {..} 中的代码)来定义数组的初始元素。

上面的答案描述了您完成此操作的方式。

于 2013-04-22T05:29:01.143 回答
0

我认为每当我们创建一个变量时,编译器都会自动为其分配内存。创建的内存量取决于您使用的编译器的类型。在第一条语句中,您使用输入声明一个数组,编译器会自动为数组元素存在于数组中,但是当您在 for 循环中声明数组时,每次运行仅创建 2 个字节。

例如。

int x; // create 2 bytes of memory

无论您是否在此空间中插入值,此空间都会永久分配给 int x。

int x = "123"; // This code also take 2 bytes of memory and contain value = 123

相似地,

int a[] ={1,2,3} // create 6 byte of space in memory, 2 byte for each integer variable.

另一方面,当您在 for 循环中声明数组而不使用新标识符时,编译器假定它是一个 int 变量并且只创建 2 个字节的内存空间并且程序会出错。

for (int n : {1, 2, 3}) // create only 2 bytes of memory

因此,通过使用新的标识符,我们分配了一个新的内存空间并插入了花括号中给出的值。

于 2013-04-22T10:11:48.700 回答
-1

老实说,我在您的解释中看到的唯一谬误是您如何告诉计算机通过不存在的对象/内存?

您必须先创建一些东西才能通过它,在这里,您什么都没有创建,并且逻辑谬误存在于您的脑海中,因为您的思考比Java本身的创建规则更深。

别担心,我发现自己遇到了像你这样的情况,但最重要的是首先要了解 Java 是如何编程的!

于 2013-04-22T10:22:16.397 回答