对于非基本类型,Java不是通过引用传递的

时间:2013-03-09 17:45:23

标签: java pass-by-reference

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

    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);

5 个答案:

答案 0 :(得分:3)

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

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

从字面上看,你说的是

aC.a = aC.a + "a"

因此,您可以将=符号解释为aC.a映射到新的String对象,该对象是aC.a"a"的串联。但是当您更改aC.a的引用时,您并未更改bC.b的引用,因此它将指向相同的旧字符串。

答案 1 :(得分:3)

你认为是什么让你感到困惑

aC.a += "a";

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

使用StringBuilder进行相同的测试,并致电

aC.a.append("a");

你会得到不同的结果。

答案 2 :(得分:3)

Java规范说Java中的所有内容都是按值传递的。 Java中没有“pass-by-reference”这样的东西。

理解这一点的关键是像

这样的东西
Dog myDog;

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

这意味着,当你有

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对象)
    • 要求Dog(地址为42的那个)将他的名字改为Max
  • 在“BBB”行
    • 创建了一只新狗。让我们说他在地址74
    • 我们将参数someDog分配给74
  • 在“CCC”行
    • someDog跟随它所指向的狗(地址为74的狗对象)
    • 要求Dog(地址为74的那个)将他的名字改为Rowlf
  • 然后,我们返回

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

myDog改变了吗?

有钥匙。

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

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

Java的工作方式与C完全相同。您可以指定指针,将指针传递给方法,按照方法中的指针操作并更改指向的数据。但是,您无法更改指针指向的位置。

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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