2011-12-31 11 views
0

私は2つのシナリオに出くわしました。Objectを引数として渡す方法は、Arrayを引数として渡す方法と異なりますか?

配列がメソッドの引数として渡され、呼び出されたメソッドで配列が更新された場合、呼び出し元のメソッドにも反映されます。

しかし、2番目のシナリオでは、Stringオブジェクトが引数として渡されます。オブジェクトは呼び出されたメソッドで更新されますが、呼び出し元のメソッドには反映されません。

どちらの場合でも、(参照の)値が引数として渡されても、2つの違いは何かを理解したいと思います。下記のスニペットをご覧ください。

シナリオ1:

class Test { 
public static void main(String[] args){ 
int a[] = {3,4,5}; 
changeValue(a); 
System.out.println("Value at Index 1 is "+a[1]); 
} 
public static void changeValue(int b[]){ 
b[1] = 9; 
} 
} 

出力:ここ

Value at Index 1 is 9 

、アレイaに関する基準(メモリアドレス)changeValueに渡されます。したがって、baと同じアドレスを指しているだけです。 したがって、私がb[1]またはa[1]と言っても、同じメモリアドレスを参照しています。

シナリオ2:

public class Test { 
public static void main(String[] args){ 
String value = "abc"; 
changeValue(value); 
System.out.println(value); 
} 
public static void changeValue(String a){ 
a = "xyz"; 
} 
} 

が出力:私はここに同じロジックを適用した場合

abc 

、文字列オブジェクトの値の参照(メモリアドレス)がaで受け取っているchangeValueに渡されています。 したがって、aは、VALUEと同じメモリ位置を参照する必要があります。したがって、a="xyz"を実行すると、​​が"xyz"に置き換えられます。

誰かが私の理解が間違っている箇所を指摘できますか?前もって感謝します!!

答えて

0

は、シナリオ1で..私は以下のように、シナリオ1と2の間の差を理解..答えと更新のために

をあなたのすべてをありがとう、配列参照が渡されます。呼び出されたメソッドは、参照によって指し示される要素の1つを更新するだけです。

シナリオ2では参照が渡されますが、呼び出されたメソッドが参照変数(ポインタ)に "xyz"を割り当てると、実際には新しいStringオブジェクトが作成され、その参照はローカル参照変数 'a '(ポインタは別のオブジェクトを指すようになりました)。呼び出されたメソッドで

コードはしたがって

a = new String("xyz"); 

ほど良好である、と呼ばれる方法でオブジェクトと呼び出し方法が全く異なるとindepenedentであり、相互に関係しません。

代わり

b[1] = 9; 

を行うので、私は私が持っている可能性がある場合は可変性のファンダメンタルズは、アクションに来ているだろう、私は理解

b = new int[] {8,9,10}; 

を使用していたならば同じことが、シナリオ1で起きている可能性が以下のようにします。

String a="abc"; 
a="xyz"; 

この場合、オブジェクト "abc"が指摘されていました'a'によって。 'a'に新しいオブジェクト "xyz"を指す義務が割り当てられると、既存のオブジェクト "abc"を置き換えない新しいオブジェクト "xyz"が作成されます。すなわち、「abc」はまだ存在するが、もはやそれ自身をアクセス可能に維持するための参照変数を有しない。この非置換プロパティは、StringのImmutabilityのためです。

2

Javaはすべての引数を値で渡します。つまり、Stringへのポインタのコピーが作成され、メソッドに渡されます。この方法では、ポインタは別のオブジェクトを指し示しますが、元のポインタは引き続き同じStringを指しています。

2

これは同じものではありません。最初の例では

  • 、あなたは、引数として配列リファレンスを渡し、したがって、あなたが正しくそれが直接参照を操作することによって変更されることを期待。しかし、2番目の例では
  • のオブジェクト参照を渡しますが、メソッド内で参照自体を変更します。メソッドが戻るときにaの変更は反映されません。

は、任意のオブジェクトを考えてみましょう:

public void changeObj(Object o) 
{ 
    o = new Whatever(); 
} 

新しいオブジェクトが作成されますが、それは、呼び出し元にoは変更されません。ここでも同じことが起こります。

+1

ここでは、不変性は赤ちゃんです。 –

+0

はい、本当に、この場合は全く問題ではありません。編集。 – fge

1

ここでの違いはシンプルであり、実際には文字列の不変性に関するものではありません。 1つのバージョン(文字列を含む)では、参照を再割り当てしましたが、他のバージョン(配列の場合)ではそうしていません。あなたは変数を再割り当てする場合

array[0] = foo; // sets an element, no reassignment to variable 
array = new int[] { 1,2,3 }; // assigns new array 
obj = "hey"; // assigns new value 

、あなたは法の外でその変化を観察するつもりはありません。配列変数を再割り当てせずに配列の要素を変更すると、それらの変更が観察されます。オブジェクトの実際の変数を再割り当てせずにオブジェクトのセッターを呼び出すと、それらの変更が観察されます。変数(新しい配列、新しい値の割り当て、新しいオブジェクトの作成など)を上書きすると、それらの変更は観察されなくなります。

引数は値渡し(またはコピー)されます。メソッド内の変数は、最初は外側の変数と同じ値を持ちます。変数はリンクされておらず、互いのエイリアスではありません。彼らはちょうど同じ値を含むことが起こります。その値を一方に再割り当てすると、それはもはや真実ではありません!外側の変数は、内部の変数、または別のローカル変数の影響を受けません。

Foo foo = new Foo(); 
Foo other = foo; 
foo.setBar(1); 
int bar = other.getBar(); // gets 1 
foo = new Foo(); 
foo.setBar(42); 
int bar2 = other.getBar(); // still gets 1 

foootherが唯一の時間のために同じオブジェクトを参照することを検討してください。 fooに新しいオブジェクトが割り当てられると、変数には共通するものがなくなりました。同じことが、メソッド内のパラメータ変数への再割り当てにも当てはまります。

1

あなたはさまざまなことをしています。パラメータ値を設定した文字列を使用して配列にという値を設定し、を参照します。

同等の配列たとえば、あなたは新しい配列に配列参照を設定しようとする必要があるでしょう:

public static void changeValue(int[] b) { 
    b = new int[] { 42, 60 }; 
} 

元の配列は変更されません。

関連する問題