web-dev-qa-db-ja.com

Javaは本当にオブジェクトを値渡ししていますか?

重複の可能性: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を渡して変更するのはなぜですか?

30
MBZ

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-タイプfFooという名前の参照を宣言し、属性_"f"_を使用してタイプFooの新しいオブジェクトに割り当てます。

_Foo f = new Foo("f");
_

Enter image description here

2-メソッド側から、名前Fooを持つタイプaの参照が宣言され、最初にnullに割り当てられます。

_public static void changeReference(Foo a)
_

Enter image description here

3-メソッドchangeReferenceを呼び出すと、参照として渡されるオブジェクトに参照aが割り当てられます。

_changeReference(f);
_

Enter image description here

4-タイプbFooという名前の参照を宣言し、属性_"b"_を使用してタイプFooの新しいオブジェクトに割り当てます。

_Foo b = new Foo("b");
_

Enter image description here

5- _a = b_は、属性が_"b"_であるオブジェクトに参照a NOT fを再割り当てしています。

Enter image description here


6- modifyReference(Foo c)メソッドを呼び出すと、参照cが作成され、属性_"f"_を持つオブジェクトに割り当てられます。

Enter image description here

7- c.setAttribute("c");は、cが参照するオブジェクトの属性を変更します。また、fが参照するオブジェクトと同じオブジェクトです。

Enter image description here

Java :)で引数としてオブジェクトを渡す方法が理解できると思います

101
Eng.Fouad

Javaでは、オブジェクトハンドルまたはオブジェクトのIDは値と見なされます。値による受け渡しは、オブジェクトの完全なコピーではなく、このハンドルを渡すことを意味します。

「参照渡し」という用語の「参照」も、「オブジェクトへの参照」を意味しません。これは、「変数への参照」、つまり値を格納できる関数定義(または、呼び出しフレーム)内の名前付き「バケット」を意味します。

参照渡しは、呼び出されたメソッドが、呼び出しメソッドで変数値を変更できることを意味します。 (たとえば、C標準ライブラリでは、関数scanfはこのように機能します。)これはJavaでは不可能です。オブジェクトのpropertiesはいつでも変更できます。これらは「値」の一部とは見なされません。それらは完全に異なる独立したオブジェクトです。

9
millimoose

obj(パラメーター)自体は変更せず、objプロパティを変更します。

重要な点は、objchangeNameの別の場所でポイントした場合、そのその変更はmainに反映されないことです。

詳細については この投稿 を参照してください。

2
Dave Newton

Objは変更されませんでした(コードは変更しません)。参照渡しされていたとしたら、次のように書くことができます。

public static void changeName(myObject obj){
    obj = new myObject("anotherName");
}

そして、メインメソッドで「anotherName」を出力させます。

2
Maurice Perry

Javaは、関数に渡すもののコピーを渡します。プリミティブ型の場合-値のコピーになります。オブジェクトの場合-参照コピーを渡します。コード例では、オブジェクトのプロパティの1つを変更していますが、参照自体は変更していないため、名前が変更されます。ただし、changeName関数でobj変数に新しいオブジェクトを割り当てる場合は、参照を変更するため、objの外側に古い値が含まれます。

1
mmatloka

これはobjへの参照を値として渡します(少しわかりにくいかもしれませんが:))。

したがって、objの値へのポインタのコピーを作成して渡すとしましょう。

つまり、次のようなことができます。

  public static void changeName(myObject obj){    
        obj.setName("anotherName");
        obj = new myObject();
    }

そして声明

System.out.print(obj.getName());

まだ古いオブジェクト(setNameを実行したオブジェクト)を参照します。

0
Mikel