为什么Java引用在本程序中没有像预期的那样工作

时间:2010-02-18 18:20:31

标签: java reference matrix

我正在解决一个问题,我发现Java引用并不像我期望的那样工作。当然,我是罪魁祸首:),有人可以请我为什么以下情况发生。我先在这里发布代码。

package misc.matrix;

public class ReferenceTester {
    public static void main(String args[]){
        Boolean[][] input = { 
            {true  ,false ,true ,true ,false },
            {false ,true  ,true ,true ,true },
            {true  ,true  ,true ,true ,true },
            {true  ,true  ,true ,true ,true },
            {true  ,false ,true ,true ,true }
        };

        print(input);

        for(Boolean[] eachRow:input){
            for(Boolean eachVal:eachRow){
                eachVal = Boolean.TRUE;
            }
        }
        print(input);

        /*Expected output  
            true  true  true  true  true  
            true  true  true  true  true  
            true  true  true  true  true  
            true  true  true  true  true  
            true  true  true  true  true
        */
    }

    /**
     * Simply prints the array
     */
    private static void print(Boolean[][] input) {
        for(Boolean[] outArray:input){
            for(Boolean iVal:outArray){
                System.out.print(iVal?iVal+"  ":iVal+" ");
            }
            System.out.println();
        }
    }
}

如果您查看上面的程序,我想要做的就是将Array中的所有值更改为true并打印它。但它只是再次打印输入。 有人可以告诉我为什么会这样。最初我在程序中使用了原始boolean,但由于我不想创建副本,我使用了包装器Boolean Class,它是一个Java OBJECT而不是原语。 (不是每个人都是JAVA OBJECT!?!?!?!?) 为什么会在Java中发生这种情况。为什么不打印所有值都是真的?

请告知。

4 个答案:

答案 0 :(得分:6)

您无法修改foreach循环中的源对象。你的循环必须是这样的循环标准:

for(int i = 0; i < input.length; i++){ 
    for(int j = 0; j < input[i].length; j++){ 
        input[i][j] = true; 
    } 
}

修改:更准确地说,循环中的eachVal指针,而不是引用;因此将其设置为指向不同的值不会更改原始值。

foreach循环在幕后使用的确切形式为here,如果您想独立确认。

答案 1 :(得分:2)

你的问题是循环改变数组的值:

    for(Boolean[] eachRow:input){
        for(Boolean eachVal:eachRow){
            eachVal = Boolean.TRUE;
        }
    }

在每次迭代中,变量eachVal保存对数组单元格内容的引用,正如您所期望的那样。但问题是,因为Boolean是一个不可变的类型 - 也就是说,你不能在创建Boolean对象之后改变它的值 - 你的任务不起作用。实际上,您实际所做的是更改eachVal引用指向的对象。也就是说,由于eachVal是来自inputeachRow的独立变量,因此您只需重新分配此变量,而无需触及数组的内容。

如果您希望我扩展或澄清任何特定观点,请告诉我。

答案 2 :(得分:1)

@mmyers得到了答案,你要求提供更多详细信息,但我无法将其纳入评论:

所以你有一个对布尔值的引用数组(它是ALWAYS引用),在你的每个循环中你创建一个引用,指向与该数组成员相同的布尔值。

每次迭代都会更新引用以指向数组中的下一个指针指向的内容。

当您使用equals时,您只需重新指定引用以指向其他内容。

如果你想更新数组中的对象,它必须是可变的(布尔不是),你必须使用mutator而不是equals。

答案 3 :(得分:1)

您尝试的内容类似于以下内容:

    int[] arr = { 1, 2, 3 };
    for (int i : arr) {
        i = 0;
    }

这不会将数组中的所有值都设置为0. Java会按值传递所有值。