【问题标题】:Array initialisation in javajava中的数组初始化
【发布时间】:2013-04-14 22:24:51
【问题描述】:

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

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[]

【问题讨论】:

    标签: java arrays int


    【解决方案1】:

    你需要这个语法:

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

    【讨论】:

    • 为什么需要new int[]?在数组声明中,不需要它,是吗?还是java编译器/解析器自动在声明中添加new int[]
    • 当你想构造对象时,你必须从'new'关键字开始。这里的 int 数组也是一个对象。
    • 这不是原因 - 请参阅第一个示例。原因是在第二个示例中,编译器不知道{1,2,3} 是什么类型。至于为什么 - 这只是一个设计决定。另一种选择是某种形式的类型推断,即猜测类型应该是什么。
    • @OneTwoThree 方括号是块声明。他们自己只是设定范围。另一方面 [] 表示这是一个数组。
    • 这每次都会分配一个new数组,对吧?带有变量声明的原始代码没有,对吧?
    【解决方案2】:

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

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

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

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

    如果数组的组件类型为 初始化是不可具体化的(§4.7)。

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

    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。回想一下short 属于int 的范围,因此在使用它时很容易遇到一些棘手/奇怪的场景。

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

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

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

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

    *:没有多少人,但那只是以防万一有

    【讨论】:

    • 稍微扩展一下歧义部分——我有时被问到“但是{"str1", "str2", "str2"} 呢,那肯定是 String[]?” ——事实并非如此。在 Java 中,所有东西(除了原语)都继承自 Object,所以即使是 {"str1", "str2"},你也可能是 String[]Object[]
    • 我认为你是正确的,但有一点需要注意。你不能以这种方式实例化一个Object,但它可以很容易地成为一个接受`String`的构造函数参数的ClassOrInterfaceType
    【解决方案3】:

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

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

    【讨论】:

    • 是的,我明白你的意思了......我想编译器/解析器可能更聪明一点!
    • 嗯,这需要 Java 区分常规代码块和数组初始化,这至少可以说是棘手的。
    • 不,但这是在 for-each 循环的两个括号内。这里没有歧义,是吗? (对不起,我是一名编译人员:D,我倾向于注意到这种东西)
    • 我认为理论上你可以在那里使用匿名方法。此外,检测到这一点只会增加更多开销,而且可能不值得。
    • 无论您是指 new byte[]、new char[]、new short[]、new int[] 还是 new long[],它还必须在可能为零的上下文中解决。它不能。所以它只能在有足够类型上下文的上下文中是合法的。这意味着它在某些情况下在语法上是合法的,但在语义上是非法的。你可以看到这是怎么回事。
    【解决方案4】:

    我认为每当我们创建一个变量时,编译器都会自动为其分配内存。创建的内存量取决于您使用的编译器的类型。在第一条语句中,您声明一个带有输入的数组,编译器会自动创建数组中存在的数组元素的空间,但是当您在 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
    

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

    【讨论】:

    • 我认为一个 int 是 4 个字节。
    • 是的,你在 java 中是对的,一个整数占用 4 个字节的内存。我采用了 C 编程语言的一般案例,因为所有编程语言的声明和初始化都是相同的
    【解决方案5】:

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

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

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

    【讨论】:

    • 我对这个答案感到困惑。我也不明白知道 Java 是如何编程的应该如何继续学习它背后的任何语法或规则。
    • 你是投票否决我的人吗?例如语法是开发人员给我们的,我们没有创建它。这就是我想说的,所以除非你没有开发过 Java,否则这些类型的问题通常是没有意义的。而且他一开始并没有初始化 Java 数组。
    • 语法可能不是我们创造的,但我们得到了规范。这是任何合理的工程师都可以遵循的,因此使这个问题非常有意义。
    猜你喜欢
    • 2013-11-28
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2013-01-20
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多