1

重複の可能性:
Javaは「参照渡し」ですか?

こんにちは私は次のコードを開発しました。swapメソッドでは、2つのオブジェクトの参照をスワップします。その後、呼び出されたメソッド(ここではswap())で変更されますが、mainメソッドでは変更されません。なぜですか?

class Check
{

    public void swap(PassByRefDemoMain obj1,PassByRefDemoMain obj2)
    {

        PassByRefDemoMain temp;
        temp=obj1;
        obj1=obj2;
        obj2=temp;
        System.out.println(obj1.id+ " "+ obj2.id);

    }
}


public class PassByRefDemoMain {
    int id;
    PassByRefDemoMain(int id)
    {
        this.id=id;
    }
public static void main(String[] args) {
        PassByRefDemoMain obj1=new PassByRefDemoMain(10);
        PassByRefDemoMain obj2=new PassByRefDemoMain(20);

        Check obj=new Check(); 
        obj.swap(obj1,obj2);

        System.out.println(obj1.id + " " + obj2.id);

    }

}
4

3 に答える 3

9

メソッドに渡すオブジェクトは参照として渡されます。つまり、メンバーの変更は外部に表示されますが、参照自体は値によって渡されます。つまり、参照の変更は呼び出し元には表示されません。これが実験です:

class Person {
    public String name;
}

class Test {
    public static void changePerson(Person p) {
         p.name = "Tudor";
         p = null;
    }

    public static void main(String[] args) {
        Person p = new Person();
        p.name = "John";
        changePerson(p);
        System.out.println(p.name); // prints Tudor and you don't get NPE
    }
}
于 2012-08-20T10:24:56.960 に答える
7

Javaは値渡しです。

オブジェクトは2つだけです。メソッドを呼び出すと、swap2つの新しい参照がコピーされますが、それらは同じオブジェクトを指します。このメソッドでは、コピーされた参照が指す場所を変更するだけです。ただし、mainメソッドの元の参照は変更されていません。

A - obj1
B - obj2

Acopy - obj1
Bcopy - obj2

方法の後:

Acopy - obj2
Bcopy - obj1

しかし、Aそれでもを指しobj1Bそれでもを指しobj2ます。

于 2012-08-20T10:25:17.440 に答える
0

人々が鋭く指摘しているように、Javaは常に価値によって渡されます。

オブジェクトの「値」は、ヒープに格納されているメモリアドレスです。だからここに何が起こるかです:

Object o = new Object();

右側はヒープにスペースを割り当てます。場所1000と言います。左側はスタックに変数を割り当てます。場所100と言います。割り当てにより、オブジェクトの「値」が含まれます。これは1000で、ヒープ上の場所です。あなたの記憶は次のようになります:

Stack
---------------------------
====== caller stack frame ==== 
100(o)    ==>     1000
==============================

Heap
------------------------------
1000   ==>   object data 1

次に、メソッド呼び出しを行います。

void foo(Object x) { .... }
foo(o);

メソッド呼び出し用に新しいスタックフレームが(明らかにスタック上に)作成されます。新しい変数がスタック上、たとえば場所200に作成され、渡されたオブジェクトの「値」(1000)が与えられると、そのオブジェクトはヒープ上の場所になります。

したがって、メソッドが実際にコードを実行する前のメモリは次のようになります

Stack
---------------------------
====== caller stack frame ====
100(o)    ==>     1000
==============================
====== foo stack frame =======
200(x)   ==>     1000
==============================

Heap
------------------------------
1000   ==>   object data 1

したがって、これをメソッドで実行すると、次のようになります。

void foo(Object x) {
   x = new Object();
}

たとえば、場所2000で新しいオブジェクトをヒープに割り当て、その場所にメソッドパラメータ変数を割り当てて、メモリが次のようになるようにします。

Stack
---------------------------
====== caller stack frame ====
100(o)    ==>     1000
==============================
====== foo stack frame =======
200(x)    ==>     2000    
==============================

Heap
------------------------------
1000   ==>   object data 1 
2000   ==>   object data 2

そして、メソッドが終了すると、スタックフレームが削除され、次の状態に戻ります。

Stack
---------------------------
====== caller stack frame ====
100(o)    ==>     1000
==============================

Heap
------------------------------
1000   ==>   object data 1
2000   ==>   object data 2

「o」は引き続き同じオブジェクトデータを指していることに注意してください。2番目に割り当てられたオブジェクト(場所2000)も、ガベージコレクションの対象になります。

于 2012-08-20T13:10:25.547 に答える