メソッドと引数のコードトレース

呼出しの前後で値がどう変わるかを検証します。仮引数への代入、配列への書込み、参照先の再指定を別々の列で追い、出力を予測します。

この単元で学ぶこと

  • メソッド宣言と呼出しを対応させる
  • 実引数と仮引数を区別する
  • プリミティブ値・参照値の値渡しを説明する

本文解説

値を二つ渡す static int score(int base,int bonus){return base+bonus*2;}へscore(10,3)と渡すと16です。score(3,10)なら23です。引数の意味を読み、式の優先順位も含めて計算します。

増分する場所 static void inc(int n){n++;}を呼ぶだけなら元の変数は変わりません。int x=4;inc(x++);なら呼出し元の後置増分によってxは5です。本体のn++と実引数式のx++は異なる変数に作用します。

配列の二段階変更 static void f(int[] a){a[0]=7;a=new int[]{9};}では、先の要素更新7は元の配列へ作用し、後の再代入は仮引数だけへ作用します。呼出し元の先頭値は7で、最後に代入した9ではありません。

同じ対象を二つの引数へ static void f(int[] a,int[] b){a[0]++;b[0]++;}へf(x,x)と渡すと、二つの仮引数は同じ配列を指します。x[0]が1なら二回増えて3です。別配列を渡す場合とは変更回数が異なります。

引数の順を追う static int code(int a,int b){return a*10+b;}にint i=1;code(++i,i++)と渡すと、左で2へ増分し2、右は2を渡して3になり、結果22です。引数をすべて評価してからメソッド本体が実行されます。

変更不能な文字列 static void f(String s){s=s+"!";}を呼んでも呼出し元のString変数は変わりません。文字列連結の結果を受取側の変数へ代入しただけです。StringBuilderのappendと同じ処理だと考えないようにします。

スコープと別名 仮引数の名前nと呼出し元の名前nが同じでも別の変数です。また一度の呼出しの仮引数が次の呼出しへ自動保存されるわけではありません。状態を持つフィールドの処理を加えていない限り、宣言と値の流れから追います。

試す組合せ プリミティブ値、空配列、一要素配列、同じ配列の二重指定、nullを分けて試します。配列アクセスの例では有効な長さも必要です。仮引数の型が合っていても、実行時の参照先や長さが不正なら例外になることを確認します。

図解

配列を引数に渡す
共有される対象と、別々に存在する変数を区別する。

重要ポイント

  • 実引数の値が仮引数へコピーされる。
  • 参照値を渡しても変数自体を共有するわけではない。
  • 共有するオブジェクトの内部変更は呼出し元にも見える。
  • 実引数は左から右へ評価する。

間違えやすい点

  • Javaを参照渡しと説明しない。
  • 仮引数への再代入で呼出し元の変数が変わると思わない。
  • 引数の型と個数の不一致を実行時エラーと混同しない。

用語解説

メソッド
名前を付けた処理。引数と戻り値を持つことがある。
実引数
呼出し時に渡す式やその評価結果。
仮引数
メソッド側で値を受け取る変数。
値渡し
値をコピーして受取側へ渡す仕組み。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。