6

假设我有一个名为TestClass.

public class TestClass {
    Foo foo;

    public TestClass(Foo foo) {
        this.foo = foo; 
    }
}

在这里,构造函数接受一个对象,它是 class 的一个实例Foo。假设 mystatic void main(String[] args)执行以下操作,与 any 完全分开TestClass

  • (1) 实例化foo

  • (2) 将实例传递fooTestClass构造函数

  • (3) 改变内部状态foo

在步骤(3)之后,我的实例foo 内部的状态TestClass 也会发生变化吗?

4

3 回答 3

14

不是通过引用传递的。相反,它是通过引用的传递的,这是一个微妙但重要的区别。

After you mutate foo in the rest of your main() method, the foo field will also exhibit these mutations, as you state, since both variables point to the same instance. However, if you reassign foo to something new, the foo field will not be changed. This would not be true if foo were truly passed by reference. In short, everything is passed by value in Java; it just so happens that objects are dealt with by reference, and so the values of these references are passed.

I'll try to illustrate this with an example. Consider the following class:

class A {
    public int n;

    public A(int n) {
        this.n = n;
    }
}

and the following method:

public static void mutate(A a) {
    a.n = 42;
}

Now we can have something like this:

A a = new A(0);
A.mutate(a);

System.out.println(a.n);
42

We can see that the state of a was changed in mutate(). Now let's modify the static method:

public static void mutate(A a) {
    a = new A(42);
}

and try again:

A a = new A(0);
A.mutate(a);

System.out.println(a.n);
0

如您所见, 的状态a没有改变。如果引用已被传递给函数,我们会期望重新分配的效果在方法范围之外是显而易见的。然而,实际上传递了一些引用,因为改变参数也会导致方法之外的变化。

于 2013-10-21T02:45:45.180 回答
3

在此处输入图像描述是的,因为您将相同的对象分配给 Foo 类的另一个引用,即对象是相同的,但被两个引用引用。

于 2013-10-21T02:39:59.357 回答
1

在第 (3) 步之后,我的 TestClass 实例中的 foo 是否也会改变其状态?

是的。

您可能想阅读此内容

更新...

现在,假设您向构造函数传递了一个原始值...

public class TestClass {
    int foo;

    public TestClass(int foo) {
        this.foo = foo; 
    }

    public String toString() {
        return "TestClass: " + foo;
    }
}

public static void main(String args[]) {
    int myFoo = 1;
    TestClass test = new TestClass(myFoo);
    myFoo += 2;
    System.out.println("myFoo = " + myFoo);
    System.out.println("yourFoo = " + test);
}

这将输出...

myFoo = 3
yourFoo = 1

这证明了更改原始值不会更改构造函数/方法维护的值的事实。

同样,如果您在传递对象引用后更改它

public class TestClass {
    Foo foo;

    public TestClass(Foo foo) {
        this.foo = foo; 
    }

    public Foo getFoo() {
        return foo;
    }
}

public static void main(String args[]) {
    Foo myFoo = new Foo();
    TestClass test = new TestClass(myFoo);
    myFoo = new Foo();
    System.out.println("myFoo == yourFoo = " + myFoo.equals(test.getFoo()));
}

将输出

myFoo == yourFoo = false

由于对象引用不一样。

于 2013-10-21T02:38:08.230 回答