都道府県穴埋めゲーム

次のソースを実行して、なぜHelloとHello,Worldが出力されるのかがよくわかりません。func()の中でa=bと参照の受け渡しが行われないのでしょうか。

class F{
static void func(StringBuffer a, StringBuffer b){
b.append(", World.");
StringBuffer w = a;
a = b;
b = w;
System.out.println("a="+a +" b=" +b);
}
}
class HelloWorld{
public static void main(String args[]){
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("Hello");
F.func(s1, s2);
System.out.println(s1);
System.out.println(s2);
}
}

A 回答 (2件)

 s1などにはStringBufferそのものが入っているわけではなく、


それはある特定のStringBufferを見て(参照して)いるのです。

 メソッドが呼び出された時点では、aにはs1と同じ内容、bにはs2と同じ内容が入っています。
すなわち、同じStringBufferを見ているのです。
よって、b.append(", World.")でs2(が参照しているStringBuffer)に文字列が追加されます。

 ただし、aとs1、bとs2は別の変数なのでaやbの内容を変更しても(参照先を入れ替えても)、
funcの中でその変更が有効に働くだけで、s1やs2までにはその変更が反映されません。
よって、s1が参照している先の内容とs2が参照している先の内容が入れ替わることはありません。

 以下のように、呼び出すメソッドに参照を入れるものの参照(配列)を渡せば、
呼び出されたメソッドでの変更を呼び出したほうにまで反映させられます。

class F {
static void func(StringBuffer[] a, StringBuffer[] b){
b[0].append(", World.");
StringBuffer w = a[0];
a[0] = b[0];
b[0] = w;
System.out.println("a="+a[0] +" b=" +b[0]);
}
}

public class HelloWorld {
public static void main(String args[]){
StringBuffer s1[] = new StringBuffer[1]; s1[0] = new StringBuffer("Hello");
StringBuffer s2[] = new StringBuffer[1]; s2[0] = new StringBuffer("Hello");
F.func(s1, s2);
System.out.println(s1[0]);
System.out.println(s2[0]);
}
}
    • good
    • 0

funcの呼び出しで、s1とs2が交換されることを期待したのだけど、


そうならなかったということですね。
これは、そうならないようになってるんです。

s1とs2には、それぞれのStringBufferのオブジェクトの参照が入っています。
つまり番地です。
s1は「このオブジェクトはXXXX番地」
s2は「このオブジェクトはYYYY番地」
という、番地を書いたメモです。
funcが呼び出されるときは、「XXXX番地」「YYYY番地」のところが
コピーされてa, bに写されます。
コピーされるだけです。それ以降のs1、s2とはもう関係がなくなります。
向こうの方で、a、bの間で値を交換しても、s1s2はそのままです。
これはC言語でも同様になります。

ファックスで書類を送ったとき、向こうで書き換えるとこちらの
書類も変わる…なんてことは起こらないでしょう。それと同じです。

では、Javaで変数を交換したいときにはどうするかというと、
簡便な方法はありません。

オブジェクトの中身をそっくり入れ替えれば、同様な効果が得られます。
StringBufferなら、deleteとかreplaceを使って中身を入れ替えるのです。
しかし、あまりそういうことはしません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!