java foreach循环中的数组引用

时间:2017-06-16 08:47:30

标签: java arrays generics foreach

我正在尝试使用for循环初始化整数java数组中的对象,但是在for循环退出后数组元素为null。

public static void main(String[] args) {
    Integer[] x = new Integer[1];
    for (Integer xx : x) {
        xx = new Integer(1);
        System.out.println("inside for loop "+xx.toString());
    }
    System.out.println("why isn't this 1?  " + x[0]);

    x[0] = new Integer(2);
    for (Integer xx : x) {
        System.out.println("Not it's okay: " + xx.toString());
    }
}

但是在for循环退出后,数组元素为null。这是输出:

inside for loop 1
why isn't this 1?  null
Not it's okay: 2

为什么这个for循环的行为与for (i=0;i<1;i++){x[i]=1;}相同?

4 个答案:

答案 0 :(得分:5)

出于完全相同的原因,这不起作用:

Integer a1 = null;
Integer a2 = a1;
a2 = new Integer(1);
System.out.println(a1.toString()); // Fails, a1 is still null

循环中的xx不是对数组元素的某种引用;相反,它是一个变量,包含数组元素值的副本(在您的情况下为null)。设置xx的值只是设置值,它对数组条目没有任何影响。

让我们通过以下代码:

Integer[] x = new Integer[1];

在记忆中,我们现在有类似的东西(忽略一些细节):

                 +−−−−−−−−−−−+
x[Ref22135]−−−−−>| Integer[] |
                 +−−−−−−−−−−−+
                 | length: 1 |
                 | 0: null   |
                 +−−−−−−−−−−−+

x内的“Ref22135”是一个名为对象引用的值,告诉JVM数组在内存中的位置。对象引用是值,就像基元一样我们处理对象的事实实际上与设置xx不会影响x[0]的原因无关,但由于你使用Integer[],我必须提及它。)< / em>的

现在,我们进入你的循环:

for (Integer xx : x) {

此时,再次忽略一些细节,我们有:

                 +−−−−−−−−−−−+
x[Ref22135]−−−−−>| Integer[] |
                 +−−−−−−−−−−−+
                 | length: 1 |
                 | 0: null   |
                 +−−−−−−−−−−−+

xx[null]

x[0]null)的值已复制xx

现在我们完成你的任务:

    xx = new Integer(1);

这给了我们:

                 +−−−−−−−−−−−+
x[Ref22135]−−−−−>| Integer[] |
                 +−−−−−−−−−−−+
                 | length: 1 |
                 | 0: null   |
                 +−−−−−−−−−−−+

                 +−−−−−−−−−−−−−+
xx[Ref99845]−−−−>|   Integer   |
                 +−−−−−−−−−−−−−+
                 | rawValue: 1 |
                 +−−−−−−−−−−−−−+

如您所见,设置xx中的值(“Ref99845”,对新Integer对象的引用)对数组没有任何影响。

请注意,这与我们处理对象的事实无关,如果我们处理原语,它将完全相同:

int[] array = new int[1];
for (int entry : array)
{
    entry = 42;
    System.out.println(entry);
}
System.out.println(array[0]);

输出:

42
0

如果我们此时停止该代码:

int[] array = new int[1];
for (int entry : array)
{
    entry = 42;

我们在记忆中看到的东西如下:

                     +−−−−−−−−−−−+
array[Ref56418]−−−−−>| int[]     |
                     +−−−−−−−−−−−+
                     | length: 1 |
                     | 0: 0      |
                     +−−−−−−−−−−−+

entry[42]

使用Integer[]时唯一的区别是从x[0]复制到xx的值是对象引用而不是int。但没关系;它仍然是一个值,当从一个事物分配给另一个事物时,值总是被复制。 (复制对象引用只会复制引用,当然不是它引用的对象)。

答案 1 :(得分:1)

你不能通过使用增强的for循环来更改数组中元素的原因是它们是如何被去除的(JLS 14.14.2):

for(int i = 0; i < x.length; i++) {
  Integer xx = x[i];
  // you're working with a variable not with the i-th element
}
// is equivalent to:
for(Integer xx : x) {
  //...
}

答案 2 :(得分:0)

您没有向数组添加值。 希望这对你有用,

    Integer[] x = new Integer[1];
    for(int i = 0 ; i<x.length ; i++){
        x[i] = new Integer(1);
        System.out.println("inside for loop "+x[i].toString());
    }
    System.out.println("why isn't this 1?  " + x[0]);

    x[0] = new Integer(2);
    for (Integer xx : x) {
        System.out.println("Not it's okay: " + xx.toString());
    }

输出

inside for loop 1
why isn't this 1?  1
Not it's okay: 2

答案 3 :(得分:0)

你的例子中的主要问题是foreach循环的使用,它不像你期望的那样工作:

Integer[] ints = new Integer[5];
for (Integer a : ints) { // assign each element of the array into the temp variable "a"
    a = new Integer(1);
}

这与:

相同
Integer[] ints = new Integer[5];
for (int i = 0; < ints.length; i++) {
    // reference "a" is pointing on the same place as reference stored in ints[i]
    // which is null, so both are pointing on null address
    Integer a = ints[i]; 
    // reference "a" is now pointing on newly allocated address with Integer(1)
    // but ints[i] is still null
    a = new Integer(1);  

    System.out.println(int[i]); // prints null
    System.out.println(a);      // prints 1
}

如果要更改数组内容,则必须直接将值分配给数组:

for (int i = 0; < ints.length; i++) {
    ints[i] = new Integer(1);   
}

但是这对于每个循环都是不可能的,它总是将array[i]复制到局部变量中。