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

2022-09-03 18:18:22

初学者Java问题,但我无法理解按值调用(或参考)在下面的示例中是如何工作的 -

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

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

答案 1

比较以下两种方法:

private static void hello(String t) {
    t = "hello " + t;
}

private static void hello(CustomStringObject o) {
    o.str = "hello " + o.str;
}

在第一种情况下,您将为 分配一个新值。这对调用代码没有影响 - 你只是改变参数的值,所有参数都是在Java中按值传递的。t

在第二种情况下,您将为 分配一个新值。这将更改 该值所引用的对象中字段的值。调用方看到该更改,因为调用方仍具有对该对象的引用。o.stro

简而言之:Java总是使用按值传递,但您需要记住,对于类,变量(或任何其他表达式)的值是一个引用,而不是一个对象。您无需使用参数传递即可看到以下内容:

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

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


答案 2

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

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

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

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