14

初学者 java 问题,但我无法理解 call-by-Value (或 Reference )在下面的示例中是如何工作的 -

在我的自定义字符串对象是退出方法后,为什么字符串值没有被修改。? 与日期等其他类相同..

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";
}
4

5 回答 5

25

比较这两种方法:

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 总是使用按值传递,但您需要记住,对于类,变量(或实际上任何其他表达式)的值是引用,而不是对象。您不需要使用参数传递来查看:

Foo foo1 = new Foo();
Foo foo2 = foo1;
foo1.someField = "changed";
System.out.println(foo2.someField) // "changed"

这里的第二行复制foo1into的值foo2- 这两个变量引用同一个对象,因此使用哪个变量来访问它并不重要。

于 2012-08-03T18:49:00.847 回答
4

这两种方法之间有一个重要的区别:使用hello(String)您试图更改对 的引用String而使用hello(CustomObject),给定一个引用,您将使用该引用更改对象的成员。

hello(String)引用 a String。在函数中,您尝试更改引用指向的对象,但您只是更改引用的按值传递副本。因此,您的更改不会反映在方法之外。

hello(CustomObject)得到一个对象引用的副本,然后您可以使用它来更改实际对象。将此视为更改对象的内容。因此,您的更改反映在调用者中。

给定一个对象的引用,您可以使用它的公开方法/字段来更改对象

于 2012-08-03T18:47:27.393 回答
0

t将指向新对象并仅限于方法,因此更改在外部不可见。

第二种情况,您正在更改的值将更新为对象,因此这些更改在方法调用后可见。

于 2012-08-03T18:47:22.490 回答
0

因为对于 String 您只是更改本地参数引用。

于 2012-08-03T18:49:10.807 回答
0

不起作用,因为 String 是不可变对象

于 2016-06-01T20:47:12.163 回答