初学者java问题,但我无法理解在下面的示例中,call-by-Value(或Reference)是如何工作的 -
为什么在我的自定义String对象退出方法后,String值不会被修改。 ?与Date等其他类相同。
public class StringMadness {
public static void main(String[] args) {
String s = "Native String";
CustomStringObject cs = new CustomStringObject();
System.out.println("Custom String Before: " + cs.str);
hello(cs);
System.out.println("Custom String After: " + cs.str);
System.out.println("Native String Before: " + s);
hello(s);
System.out.println("Native String After: " + s);
}
private static void hello(String t) {
t = "hello " + t;
}
private static void hello(CustomStringObject o) {
o.str = "hello " + o.str;
}
}
class CustomStringObject {
String str = "Custom String";
}
答案 0 :(得分:23)
比较这两种方法:
private static void hello(String t) {
t = "hello " + t;
}
private static void hello(CustomStringObject o) {
o.str = "hello " + o.str;
}
在第一种情况下,您要为t
分配一个新值。这对调用代码没有影响 - 你只是改变一个参数的值,所有的参数都是用Java中的值传递的。
在第二种情况下,您要为o.str
分配一个新值。这会改变o
所指的对象中的字段的值。调用者将看到该更改,因为调用者仍然具有对该对象的引用。
简而言之:Java总是使用pass by value,但是您需要记住,对于类,变量(或实际上任何其他表达式)的值是引用,而不是对象。您不需要使用参数传递来查看:
Foo foo1 = new Foo();
Foo foo2 = foo1;
foo1.someField = "changed";
System.out.println(foo2.someField) // "changed"
此处的第二行将foo1
的值复制到foo2
中 - 两个变量引用同一个对象,因此使用哪个变量访问它无关紧要。
答案 1 :(得分:4)
这两种方法之间存在重大差异:使用hello(String)
您尝试将引用更改为String
,并使用hello(CustomObject)
您正在使用引用来更改对象的成员。
hello(String)
会引用String
。在函数中,您尝试更改引用所指向的对象,但您只是更改引用的按值传递值。因此,您的更改不会反映在方法之外。
hello(CustomObject)
会获得一个对象的引用副本,然后您可以使用该副本来更改实际对象。可以将此视为更改对象的内容。因此,您的更改 会在调用方中反映出来。
给定对象的引用,您可以使用它公开的方法/字段来更改对象
答案 2 :(得分:0)
t
将指向新对象并仅限于方法,因此更改在外部不可见。
第二种情况,您要更改的值将更新为object,因此在方法调用后可以看到这些更改。
答案 3 :(得分:0)
因为对于String,您只是更改本地参数引用。
答案 4 :(得分:0)
不起作用,因为String是一个不可变对象