Java传值价值混乱

时间:2013-09-12 11:48:17

标签: java pass-by-value

有点奇怪的问题。我有以下代码,它只创建一个名为DumObj的简单java对象,并使用setter方法设置字符串值。然后使用DumObj作为参数从TestBed类调用一些方法。

我最初认为调用TestBed.updateId(DumObj)不会影响我的DumObj,并且设置为“apple”的ID的初始值将保持不变。 (因为整个价值传递的东西)

然而,ID的值被设置为更新的“橙色”值。好吧,我想,这很奇怪,所以我写了另一个方法TestBed.setToNull(DumObj)。这个方法只是将DumObj设置为null,所以当我调用getId()方法时,我希望得到一个空指针异常。

然而,我得到的输出是ID的值仍然设置为“橙色”。

代码如下:

    public static void main(String[] args) 
    {   
            TestBed test = new TestBed();
            DumObj one = new DumObj();

            one.setId("apple");
            System.out.println("Id : " + one.getId());

            test.updateId(one);
            System.out.println("Id : " + one.getId());

            test.setToNull(one);
            System.out.println("Id : " + one.getId());
    }

    public void updateId(DumObj two)
    {
            two.setId("orange");
    }

    public void setToNull(DumObj two)
    {
            two = null;
    }

输出如下:

    Id : apple
    Id : orange
    Id : orange

这可能是我忽视的非常简单的事情,但有人可以向我解释这种行为吗? Java不是按值传递吗?

5 个答案:

答案 0 :(得分:2)

写作时

DumObj one = new DumObj();

重要的是要认识到one不是DumObj - 它是引用DumObj,引用是按值传递

所以你总是按值传递,你可以改变传递的引用(所以传递的引用现在指向另一个对象)。但是,你的对象本身可能是可变的,所以:

   one.setValue(123);

将更改引用的对象。当你这样称呼时:

public void setToNull(DumObj two)
{
        two = null;
}

你正在改变传递的引用(记住 - 它已经通过值传递 并且是方法的本地!)因此你的原始对象和原始引用不会受到影响。

答案 1 :(得分:2)

当你这样做时:

two = null;

您只是将two变量引用设置为null。它指向的对象仍然存在,并由one引用。

另一方面,当你这样做时:

two.setId("orange");

您正在修改onetwo引用的对象。

答案 2 :(得分:0)

Java是对象的“按值传递引用”。所以在setToNull(DumObj two)中,两个是对象的引用。如果你说two = null;,那么现在使两个引用不是一个对象;它不会改变对象。另一方面,如果您执行two.setId("blue")之类的操作,则表示您正在更改two引用的对象。

答案 3 :(得分:0)

是的,Java是值得传递的。但是你的变量实际上是指向堆上分配的对象的指针。那么它通过值传递的是指针,而不是对象。

在您的示例中:

public void updateId(DumObj two)
{
        two.setId("orange");
}

第一个按值传递变量(指针),即updateId()接收指针的副本。但你在这里做的是修改指针指向的对象。因此,当您返回调用函数时,对象被修改。

public void setToNull(DumObj two)
{
        two = null;
}

在第二种情况下,您将null分配给原始指针的副本,而不是原始指针本身,以便函数调用在原始变量中完全没有效果

答案 4 :(得分:0)

当你调用updateId时,新的引用变量2和旧引用变量一引用堆中的同一个对象,所以改变一个会反映在其他引用变量中。

现在当你再次调用setToNull时,新的引用变量二和旧引用变量一引用同一个对象。但是当你执行两个= null 时,只引用变量两个指向null对象。但是引用变量仍然指向同一个对象。当你执行两个== null 时,你不会改变它引用的对象中的任何值,而是将引用变量引用为null。

如果在setToNull方法中你写了两个= new DumObj();然后将创建堆中的新对象,并且两个将指向此新对象。然后如果您编写则为ex 的 two.setId( “香蕉”);

并且在主代码中,如果你在syso中写一个.getId(),那么它将打印橙色而不是香蕉。

希望我帮忙。