0

在下面的代码中,我假设两个对象都引用了同一个对象,但下面的示例说我错了。对不起,如果它是重复的。

    class A {
        public String a;
        public void set(String a) {
            this.a = a;
        }
    }

    class B {
        public String b;
        public void set(String b) {
            this.b = b;
        }
    }

    A aC = new A();
    B bC = new B();

    String str = "aaa";

    aC.set(str);
    bC.set(aC.a);

    aC.a += "a";

    System.out.println(aC.a);
    System.out.println(bC.b);
4

5 回答 5

3

Java 是按值传递的。引用是按值传递的。

aC.a += "a"创建一个新的 String 对象,这就是它没有反映在 bC 中的原因。

从字面上看,你是说

aC.a = aC.a + "a"

因此,您可以将该=符号解释为aC.a映射到一个新的 String 对象,该对象是aC.aand的串联"a"。但是当你改变你的引用时,aC.a你并没有改变 的引用bC.b,所以它会指向同一个旧字符串。

于 2013-03-09T17:46:13.310 回答
3

让你困惑的是你认为

aC.a += "a";

修改 . 引用的 String 对象的状态aC.a。事实并非如此。字符串是不可变的,上面的代码行创建了一个新的 String 对象并将其分配给 aC.a,保留对原始对象的所有其他引用。

使用 a 进行相同的测试StringBuilder,然后调用

aC.a.append("a");

你会得到不同的结果。

于 2013-03-09T17:48:53.737 回答
3

Java 规范说 Java 中的所有内容都是按值传递的。Java 中没有“按引用传递”之类的东西。

理解这一点的关键是

Dog myDog;

不是狗;它实际上是一个指向 Dog 的指针。

这意味着,当你有

Dog myDog = new Dog("Rover");
foo(myDog);

您实际上是将创建的 Dog 对象的地址传递给 foo 方法。

(我说本质上 b/c Java 指针不是直接地址,但这样想它们是最容易的)

假设 Dog 对象位于内存地址 42。这意味着我们将 42 传递给方法。

如果方法被定义为

public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}

让我们看看发生了什么。

  • 参数 someDog 设置为值 42
  • 在“AAA”行
    • someDog 跟随它指向的 Dog(地址 42 处的 Dog 对象)
    • 那条狗(地址为 42 的那只)被要求将他的名字改为 Max
  • 在“BBB”行
    • 创建了一个新的 Dog。假设他在地址 74
    • 我们将参数 someDog 分配给 74
  • 在“CCC”行
    • someDog 跟随它指向的 Dog(地址 74 处的 Dog 对象)
    • 那条狗(地址为 74 的那只)被要求将他的名字改为 Rowlf
  • 然后,我们返回

现在让我们考虑一下在方法之外会发生什么:

myDog 变了吗?

有钥匙。

请记住,myDog 是一个指针,而不是真正的 Dog,答案是否定的。myDog 的值仍然是 42;它仍然指向原来的 Dog。

跟随地址并更改其末尾的内容是完全有效的;但是,这不会改变变量。

Java 的工作方式与 C 完全一样。您可以分配指针、将指针传递给方法、跟随方法中的指针并更改指向的数据。但是,您不能更改该指针指向的位置。

于 2013-03-09T18:06:55.697 回答
1

JVM 中有三个字符串对象。“aaa”、“a”和“aaaa”(因为字符串是不可变的)。最初 aC.a 和 bC.b 指向同一个字符串对象“aaa”。在这一行 aC.a += "a"; 代码将 aC.a 的引用更改为指向“aaaa”。所以现在 aC.a -> "aaaa" 和 bC.b -> "aaa"。我希望我很清楚。

于 2013-03-09T18:43:25.953 回答
0

Java实际上是按值传递的。实际引用被复制,并且该副本被发送到函数。

于 2013-03-09T17:46:52.613 回答