[英]Java Pass-by-Value Confusion
好的一个奇怪的问题。 我有以下代码,该代码仅创建一个简单的java对象DumObj并使用setter方法设置字符串值。 然后使用DumObj作为参数从TestBed类中调用一些方法。
最初,我认为调用TestBed.updateId(DumObj)不会影响我的DumObj,并且设置为“ apple”的ID的初始值将保持不变。 (因为整个价值传递的事情)
但是,ID的值被设置为“橙色”的更新值。 好的,我认为那很奇怪,所以我编写了另一种方法TestBed.setToNull(DumObj)。 此方法只是将DumObj设置为null,因此当我调用getId()方法时,我期望得到一个null指针异常。
但是我得到的输出是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不是按值传递的吗?
当你写
DumObj one = new DumObj();
重要的是要意识到one
不是DumObj
,而是对DumObj
的引用 ,并且引用是通过value传递的 。
因此,您始终按值传递,并且可以更改传递的引用(因此,传递的引用现在指向另一个对象)。 但是,您的对象本身可能是可变的,因此:
one.setValue(123);
将更改引用的对象。 当您致电:
public void setToNull(DumObj two)
{
two = null;
}
您正在更改传递的引用(请记住-它已通过值传递并且在方法中是本地的!),因此您的原始对象和原始引用不受影响。
当您这样做时:
two = null;
您仅将two
变量引用设置为null。 它指向的对象仍然存在,并被one
引用。
另一方面,当您这样做时:
two.setId("orange");
您正在修改one
和two
都引用的对象。
Java是对象的“按值传递引用”。 因此,在setToNull(DumObj two)
,两个是对对象的引用。 如果说two = null;
现在,这两个引用不是对象。 它不会改变对象。 另一方面,如果您执行诸如two.setId("blue")
,则您正在更改two
引用的对象。
是的,Java是按值传递的。 但是您的变量实际上是指向在堆上分配的对象的指针。 因此,它所传递的值是指针,而不是对象。
在您的示例中:
public void updateId(DumObj two)
{
two.setId("orange");
}
第一个按值传递变量(指针),即updateId()
获得指针的副本。 但是您在这里所做的是修改指针所指向的对象 。 因此,当您返回调用方函数时,该对象已被修改。
public void setToNull(DumObj two)
{
two = null;
}
在第二种情况下,您将null
分配给原始指针的副本,而不是原始指针本身 ,因此该函数调用对origial变量完全无效。
当您调用updateId时,新引用变量2和旧引用变量1都引用堆中的同一对象,因此更改一个引用将反映在其他引用变量中。
现在,当您再次调用setToNull时,新的参考变量2和旧的参考变量1都引用同一对象。但是在这里,当您执行两个= null时,仅参考变量2指向空对象。 但是引用变量one仍然指向同一对象。当您执行two == null时 ,您没有更改它引用的对象中的任何值,而是将引用变量引用为null。
如果使用setToNull方法,则编写两个= new DumObj();。 然后将在堆中创建一个新对象,并且两个对象将指向该新对象。然后,例如,如果您编写两个,则为.setId(“ banana”);
并且在您的主代码中,如果您在syso中编写one.getId(),它将显示橙色而不是香蕉。
希望我能帮上忙。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.