「参照渡し」の言葉自体が物議を醸していたりしますが・・・。内容については、ここでは語りません。
とは言え、「参照渡し」は一般的に普及した言葉ですので、とりあえずこの言葉を使います。
いぢわるな例(ふつう、こうは書かない)で申し訳ないですが、ハマる例ってことで。
まずは、もとになるVBから。
1 2 3 4 5 6 7 8 9 10 11 12 | Public Class StringRefTest Public Sub execute() Dim str As StringBuilder getStr(str) Console.WriteLine(str) End Sub Public Sub getStr(ByRef str as StringBuilder) str = new StringBuilder("バグが出た!") End Sub End Class |
そのまま、Javaに書きかえます。
1 2 3 4 5 6 7 8 9 10 11 12 | public class StringRefTest { public void execute() { StringBuilder str = new StringBuilder(); getStr(str); System.out.println(str); } public void getStr(StringBuilder str) { str = new StringBuilder("バグが出た!"); } } |
何も出てきません・・・。(本当は、空文字が出力されてます)
修正方法は?
解説の前に修正方法です。
いくつかありますが、Javaを知っている人であれば、すぐに思いつくのは下の2つだと思います。
- void getStr(StringBuilder)をやめて、StringBuilder getStr()に変える。
- void getStr(StringBuilder str)の引数strに対して、appendする。
1つ目は、主旨と外れて面白くないので、2つ目の例だけ書きます。(ふつうは、1つ目・・)
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class StringRefTest { public void execute() { StringBuilder str = new StringBuilder(); getStr(str); System.out.println(str); } public void getStr(StringBuilder str) { str.append("バグが出た!"); } } |
目論見通り、もちろん、コンソールに「バグが出た!」が出力されます。
何でこうなるの?
VBの参照渡しとJavaの参照渡しの違いです。
- Javaの場合、渡されたポインタは、渡す元のポインタをコピーしたもの。(つまり、渡し元と渡し先でポインタが別物)
- VBの場合、渡したポインタにオブジェクトを指すようにしてくれるため。(つまり、渡し元と渡し先でポインタ自体が一緒)
世界は、不思議でいっぱいです。
VBからJavaに変わったみなさんは、要注意です。
最初っからJavaの人は、VBを見ると・・・Σ(゚Д゚)