Java - 方法调用后对象状态不会更改

时间:2012-08-03 18:46:05

标签: java pass-by-reference pass-by-value

初学者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";
}

5 个答案:

答案 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是一个不可变对象