重複の可能性:Is Java参照渡し?
public class myClass{
public static void main(String[] args){
myObject obj = new myObject("myName");
changeName(obj);
System.out.print(obj.getName()); // This prints "anotherName"
}
public static void changeName(myObject obj){
obj.setName("anotherName");
}
}
Java値で渡すことを知っていますが、前の例で参照によってobj
を渡して変更するのはなぜですか?
Javaは常に、参照ではなく値によって引数を渡します。あなたの例では、参照自体ではなく、その値によってobj
を渡しています。メソッドchangeName
内で、引数として渡した同じオブジェクトに別の(ローカル)参照obj
を割り当てています。その参照を変更すると、引数として渡される元の参照obj
が変更されます。
編集:
例を通してこれを説明しましょう:
_public class Main
{
public static void main(String[] args)
{
Foo f = new Foo("f");
changeReference(f); // It won't change the reference!
modifyReference(f); // It will change the object that the reference refers to!
}
public static void changeReference(Foo a)
{
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c)
{
c.setAttribute("c");
}
}
_
これを段階的に説明します。
1-タイプf
のFoo
という名前の参照を宣言し、属性_"f"
_を使用してタイプFoo
の新しいオブジェクトに割り当てます。
_Foo f = new Foo("f");
_
2-メソッド側から、名前Foo
を持つタイプa
の参照が宣言され、最初にnull
に割り当てられます。
_public static void changeReference(Foo a)
_
3-メソッドchangeReference
を呼び出すと、参照として渡されるオブジェクトに参照a
が割り当てられます。
_changeReference(f);
_
4-タイプb
のFoo
という名前の参照を宣言し、属性_"b"
_を使用してタイプFoo
の新しいオブジェクトに割り当てます。
_Foo b = new Foo("b");
_
5- _a = b
_は、属性が_"b"
_であるオブジェクトに参照a
NOT f
を再割り当てしています。
6- modifyReference(Foo c)
メソッドを呼び出すと、参照c
が作成され、属性_"f"
_を持つオブジェクトに割り当てられます。
7- c.setAttribute("c");
は、c
が参照するオブジェクトの属性を変更します。また、f
が参照するオブジェクトと同じオブジェクトです。
Java :)で引数としてオブジェクトを渡す方法が理解できると思います
Javaでは、オブジェクトハンドルまたはオブジェクトのIDは値と見なされます。値による受け渡しは、オブジェクトの完全なコピーではなく、このハンドルを渡すことを意味します。
「参照渡し」という用語の「参照」も、「オブジェクトへの参照」を意味しません。これは、「変数への参照」、つまり値を格納できる関数定義(または、呼び出しフレーム)内の名前付き「バケット」を意味します。
参照渡しは、呼び出されたメソッドが、呼び出しメソッドで変数値を変更できることを意味します。 (たとえば、C標準ライブラリでは、関数scanf
はこのように機能します。)これはJavaでは不可能です。オブジェクトのpropertiesはいつでも変更できます。これらは「値」の一部とは見なされません。それらは完全に異なる独立したオブジェクトです。
obj
(パラメーター)自体は変更せず、obj
のプロパティを変更します。
重要な点は、obj
をchangeName
の別の場所でポイントした場合、そのその変更はmain
に反映されないことです。
詳細については この投稿 を参照してください。
Objは変更されませんでした(コードは変更しません)。参照渡しされていたとしたら、次のように書くことができます。
public static void changeName(myObject obj){
obj = new myObject("anotherName");
}
そして、メインメソッドで「anotherName」を出力させます。
Javaは、関数に渡すもののコピーを渡します。プリミティブ型の場合-値のコピーになります。オブジェクトの場合-参照コピーを渡します。コード例では、オブジェクトのプロパティの1つを変更していますが、参照自体は変更していないため、名前が変更されます。ただし、changeName関数でobj変数に新しいオブジェクトを割り当てる場合は、参照を変更するため、objの外側に古い値が含まれます。
これはobjへの参照を値として渡します(少しわかりにくいかもしれませんが:))。
したがって、objの値へのポインタのコピーを作成して渡すとしましょう。
つまり、次のようなことができます。
public static void changeName(myObject obj){
obj.setName("anotherName");
obj = new myObject();
}
そして声明
System.out.print(obj.getName());
まだ古いオブジェクト(setNameを実行したオブジェクト)を参照します。