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

参照渡しではありません。むしろ、参照のによって渡されます。これは微妙ですが重要な違いです。

メソッドfooの残りの部分を変更すると、両方の変数が同じインスタンスを指しているためmain()、フィールドもこれらの変更を示します。fooただし、新しいものに再割り当て しても、フィールドは変更されません。本当に参照によって渡された場合、これは当てはまりません。つまり、Java ではすべてが値渡しされます。たまたまオブジェクトが参照によって処理されるため、これらの参照の値が渡されます。foofoofoo

これを例で説明しようと思います。次のクラスを検討してください。

class A {
    public int n;

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

そして次の方法:

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

これで、次のようなものができます。

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

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

aで の状態が変化したことがわかりますmutate()。それでは、静的メソッドを変更しましょう。

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

そしてさらに試みる:

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

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

ご覧のとおり、 の状態aは変更されていません。参照が関数に渡された場合、メソッドのスコープを超えて再割り当ての効果が明らかになると予想されます。それにもかかわらず、引数を変更するとメソッドの外部でも変更が発生したため、実際にはいくつかの参照が渡されました。

于 2013-10-21T02:45:45.180 に答える
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 に答える