布尔数组能否在for循环中初始化?

20

刚刚发现了这个Stack Overflow上的问题,恰好解决了我在Java中初始化布尔数组的问题。initializing a boolean array in java。然而,虽然它给了我可以工作的代码,但提问者并没有尝试我正在运行但不工作的代码,我实际上想知道为什么它不工作。这是我正在尝试的代码:

Boolean[] array = new Boolean[5];
for(Boolean value : array) {
    value = false;
}

这是来自另一个问题的可运行代码:

Boolean[] array = new Boolean[5];
Arrays.fill(array, Boolean.FALSE);

我只是好奇为什么使用for循环的方法不起作用?


5
这是Java引用按值传递的问题。随着每次迭代,它将其分配给“value”变量,但当您将“value”分配为false时,您正在覆盖引用而不是数组内实际的变量。对于每个从不在向数组赋值时都不起作用。 - Nathan Merrill
真的很好知道。谢谢 @MrTi,我很惊讶自己之前居然没有遇到过这个问题。 - sage88
8个回答

18
Boolean[] array = new Boolean[5];
for(Boolean value : array) {
    value = false;
}
Java增强的for循环使用迭代器遍历数组。迭代器返回对象的引用,但是Java按值传递引用,因此您无法更改引用指向的内容,这正是您尝试使用value = false进行的操作。 编辑:
事实证明,对于普通的数组,Java不需要将其转换为List并使用迭代器,而是采取以下方式:
for (int i = 0; i < array.length; i++) 
{
    Boolean value = array[i]; //here's how we get the value that's referred to 
    ...                       //in the enchanced for loop  
}
尽管我们没有使用迭代器,但 Java 按值传递引用的事实仍然解释了这里发生的事情。
如果这是一个具有某些实例成员的对象数组,您将能够更改这些成员,但不能更改对象本身所引用的内容。
正如其他人建议的那样,为了解决这个问题,只需使用常规的 for 循环并手动为数组中的索引位置分配值即可:
Boolean[] b_values = new Boolean[5];
for(int i = 0; i < b_values.length; i++) 
{
    b_values[i] = Boolean.FALSE; 
}

4
我发现这里有很多回答并没有真正回答问题,这让我感到震惊。 - Nathan Merrill
1
从技术上讲,对于数组,Java 不使用迭代器。 - user2357112
@SteveP.: 在这里。 向下滚动到从“否则,表达式必须具有数组类型”开始的部分。 - user2357112
1
@sᴜʀᴇsʜᴀᴛᴛᴀ 刚刚看了一下,我知道他们在结尾列出的 for-each 循环的大多数缺陷,但显然不是最重要的一个。我可能之前尝试过这个,但没有成功,只是想都没想就回到了标准的 for 循环。 - sage88
1
@sage88 程序员的生活 :) - Suresh Atta
显示剩余17条评论

4
代码无法运行的原因是,当您提到时,代码中的某些部分缺失或存在错误。
Boolean[] array = new Boolean[5];
for(Boolean value : array) {
    value = false;
}

你实际上创建了一个名为“布尔数组”的新引用类型,它仅包含对Boolean类的五个对象的引用,但由于你尚未创建这些对象,因此该对象不存在。
而在第二段代码中,
Boolean[] array = new Boolean[5];
Arrays.fill(array, Boolean.FALSE);

您正在使用Boolean类的缓存对象,并将其添加到使用java.util.Arrays类创建的数组中。Boolean是Java中的包装类,因为只有两个可能的值可以避免在创建它们时产生额外的开销,因此Java已经为您创建了它们并使它们可供立即使用。

3

value = true; 内部实际上是 value = new Boolean(true); 即在池中创建了一个新的对象。value 对象引用了该 Boolean 对象。包装类是不可变的。

enter image description here


2

是的,Boolean[]可以在for循环中初始化。为此,您需要使用数组索引设置值,而不是增强的for循环。请查看以下循环。

Boolean[] array = new Boolean[5];
for(int i=0;i<array.length;i++) {
    array[i] = Boolean.FALSE;
}

在我看来,这非常模糊。 - Steve P.
1
这绝对可行,我认为这是我最喜欢的实现方式。不过,Steve P的回答更贴近我的问题。 - sage88

1

因为value是数组element的副本,而不是数组中实际的元素。

Boolean[] array = new Boolean[5];    
    for (int i = 0; i < array.length; i++) {
             array[i]= false;           
    }

仅供参考:

如下:How for each works


0
它是一个布尔引用数组,没有真实的对象被分配。你需要这样做。
Boolean[] array = new Boolean[5];
for(Boolean value : array) {
    value = new Boolean(false);
}

编辑: 这并没有解决问题。它还是一样的。在for循环中,变量值不是对原始数组的引用。这就是为什么你需要这样做。

Boolean[] array = new Boolean[5];    
for (int i = 0; i < array.length; i++) {
    array[i]= false;           
}

0
为了说明“更改引用”和“更改成员的引用值”的问题,我尝试使用自定义类进行操作,并在此处发布我所尝试的内容和观察结果 - 感谢 @SteveP。
//情况1 尝试更改引用
    Boolean[] array1 = new Boolean[5];
    Arrays.fill(array1, Boolean.FALSE);
    for(Boolean value : array1) { // Warning here The value of the local variable value is not used
        value = Boolean.TRUE;
    }

    System.out.println(" Elements ==> "+array1[0]+" -  "+array1[1]);

这将打印出元素 ==> false - false ,引用将无法修改

情况2 尝试使用用户定义的类更改引用

        MyBool[] array3 = new MyBool[5];
    MyBool boolInst2=new MyBool( Boolean.FALSE);
    MyBool boolNew=new MyBool( Boolean.TRUE);

    Arrays.fill(array3,boolInst2 );
    for(MyBool value : array3) {  // Warning here The value of the local variable value is not used
        value = boolNew;
    }
    System.out.println(" Elements ==> "+array3[0].flag+" -  "+array3[1].flag);

这将打印出元素 ==> false - false,引用将无法修改

情况3 改变对象成员的值(MyBool.value),

            MyBool[] array2 = new MyBool[5];
    MyBool boolInst=new MyBool( Boolean.FALSE);
    Arrays.fill(array2,boolInst );
    for(MyBool value : array2) {
        value.flag = Boolean.TRUE;
    }
    System.out.println(" Elements ==> "+array2[0].flag+" -  "+array2[2].flag);

这将打印出元素 ==> true - true ,值已更新

class MyBool{
    public Boolean flag;
    public MyBool(Boolean flag){
        this.flag=flag;
    }
}

0

简而言之: 在使用for循环枚举数组时,您不能修改正在迭代的集合元素。把它看作只读。


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