2013年4月22日月曜日

Javaの関数の引数について ーJavaの値渡しと参照渡しの誤解ー

昨日Twitterで宣言しましたが、Javaの引数について書きたいと思います。

Javaの引数は基本的に、

プリミティブ型=Call By Value = 値渡し
オブジェクト型=Call By Reference = 参照渡し

になります。

で、Call By Referenceの説明で
String型を使って以下の説明をしているのが多くあります。

さあ、ここで問題です!
出力は何になるでしょうか?

答えは、
”before method call”
です。

当たり前です(^^)/

C言語で書くと、


こうやってるのと同等です。

それ、C言語で言うと、ポインタのポインタを使わないと
出来ませんよ^^;;;

あと、



これも同じです!
これも同じC言語のポインタのポインタ使わないと^^;;;

Call By Referenceの説明で、上の例を使って、Call By Referenceだけど・・・
なんて説明しているのは間違いです!

C言語でいう、ポインタの概念をちゃんと理解しないと実は
この辺りって理解が難しいかもですね!

あ!
constじゃないととか、そういうツッコミはなしね^^
あくまで例なので!

6 件のコメント:

  1. そもそもJavaって他の言語一般で言う参照渡しじゃなくて、Handle渡しなんですよね。
    JREの実装でもReference型でObjectを管理してるわけじゃなく、Handle型でObjectを管理してるんですから、素直にHandle渡しとかいてれば誤解は少ないのかもしれません。

    返信削除
    返信
    1. コメントありがとうございます!

      へぇそうなんですね!
      Handle型でjavaはオブジェクトを管理しているってのは初めてしりました!

      ちなみにHandle型というのは、私の認識だと、Cでいう、ポインタのポインタ
      (アドレスのアドレス)なのですが、認識はあっていますでしょうか?

      削除
    2. 構造上PointerのPointerに似ていますがちょっと違います。
      *handle->body;
      こんな感じでPointerを持つ構造体へのPointerでも構いませんから。
      Open JDKなんかはモロにそんな実装ですね。

      ちなみに、Javaも引き数から文字列を返せる事をご存知です?
      こんな感じで受け取ることができます。

      void getName( String[] name )
      {
      name[0] = "名前";
      }

      このやり方がいいかどうかはひとまず置いといて、
      PointerのPointerと構造は同じなんですよね。
      (あくまでPointer[記憶空間上の座標]じゃなくHandleですが)

      削除
    3. コメントありがとうございます!

      おお!
      なるほど!
      そういう実装になっているんですね!

      文字列の引数返しもなるほどです!
      やり方はさておき、確かにString[]にしてしまえば、
      構造上はPointerのPointerですので、返せますね!
      とても勉強になります!ありがとうございます!

      個人的にはPointerってのは凄く言葉としてわかり辛いと
      思ってます。
      アセンブラと同じで、なんでアドレスじゃないのかなぁと、
      いつも不思議に思ってます。

      削除
  2. >アセンブラと同じで、なんでアドレスじゃないのかなぁと、
    >いつも不思議に思ってます。
    Wikipediaにも乗ってる話ですが一次元記憶空間の座標(Point)を指してるからでしょうね。
    Pointerは、一次元空間における座標としての演算は受け付けますが、掛け算の様な座標には適用できない演算は受け付けません。

    返信削除
    返信
    1. コメントありがとうございます!

      Wikipediaにはそう言った事ものってるんですね!
      確かにかけ算等は受け付けないですね!

      というか、

      int *a = malloc(sizeof(int));
      a *= 2;

      なんて(もしできたとして)やったら吹っ飛んじゃいますね(笑)

      削除