2

好吧,有点奇怪的问题。我有以下代码,它只是创建了一个名为 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不是按值传递吗?

4

5 回答 5

2

当你写

DumObj one = new DumObj();

重要的是要意识到这one不是DumObj- 它是对 的引用DumObj并且引用是按值传递的

所以你总是按值传递,你可以改变传递的引用(所以你传递的引用现在指向不同的对象)。但是,您的对象本身可能是可变的,因此:

   one.setValue(123);

将更改引用的对象。当你调用这个时:

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

您正在更改传递的引用(请记住 - 它是按值传递的,并且是方法本地的!)因此您的原始对象和原始引用不受影响。

于 2013-09-12T11:50:02.937 回答
2

当你这样做时:

two = null;

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

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

two.setId("orange");

您正在修改 和 引用的one对象two

于 2013-09-12T11:51:50.963 回答
0

当您调用 updateId 时,新引用变量二和旧引用变量一都引用堆中的同一对象,因此更改一个会反映在其他引用变量中。

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

如果您在 setToNull 方法中编写 two=new DumObj(); 然后将在堆中创建一个新对象,其中两个将指向这个新对象。如果你写 了 two.setId("banana");

在您的主代码中,如果您在 syso 中编写 one.getId() ,那么它将打印橙色而不是香蕉。

希望我有所帮助。

于 2013-09-12T11:56:42.860 回答
0

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

于 2013-09-12T11:52:54.373 回答
0

是的,Java 是按值传递的。但是您的变量实际上是指向堆上分配的对象的指针。所以它通过值传递的是指针,而不是对象。

在您的示例中:

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

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

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

在第二种情况下,您正在分配原始指针null副本,而不是原始指针本身,因此该函数调用在原始变量中根本没有影响。

于 2013-09-12T11:54:56.197 回答