戻り値とvoidのコードトレース
呼出し式を大きな式へ組み合わせ、早期returnや複数経路の結果を追います。画面への出力順と返された値を別に記録します。
この単元で学ぶこと
- 戻り値と標準出力を区別する
- voidと値を返すメソッドの宣言を使い分ける
- returnの位置と型を検証する
本文解説
呼出し結果を計算 static int square(int n){return n*n;}ならsquare(2)+square(3)は4+9=13です。呼出しをそれぞれ評価した値へ置き換えると、式全体が追いやすくなります。呼出しの回数分だけ本体が動きます。
入れ子の呼出し static int inc(int n){return n+1;}でinc(inc(2))は4です。実引数として必要な内側のinc(2)を3に評価してから、外側へ3を渡します。外側の本体が先に2を処理するわけではありません。
早期return static void show(int n){if(n<0)return;System.out.print(n);}をshow(-1);show(2);と呼ぶと2だけを表示します。一つ目の呼出しから戻ってもmainの次の呼出しは残ります。returnで全プログラムを終了するわけではありません。
表示しながら返す static int f(){System.out.print("A");return 2;}にSystem.out.print(f()+1);を実行するとA3です。まず本体内のA、次に呼出し式の戻り値を使って3が表示されます。戻り値が一つでも、副作用の表示が別に起きる場合があります。
正常に終わらない経路 static int f(boolean ok){if(ok)return 1;throw new IllegalArgumentException();}はコンパイル可能です。okがfalseの経路は例外を送出し、値なしで正常に末尾へ到達しないためです。「必ず各行にreturnを書く」ではなく正常終了の経路を確認します。
参照を受け取る static int[] f(){return new int[]{3};}の戻り値をint[] a=f();で保存すると、その配列をa[0]=7と変更できます。別々にf()を呼ぶとnewを二回実行し別の配列を作ります。参照を返すことと毎回同じ対象を返すことは同じ意味ではありません。
結果を保存し忘れる static int inc(int n){return n+1;}にint x=3;inc(x);とだけ書いてもxは3です。x=inc(x);なら4です。計算用メソッドの戻り値を受け取らない誤りはコンパイルで必ず検出されるものではありません。
型の境界 static double f(){return 3;}は3.0相当のdoubleを返します。int x=f();は暗黙の縮小ができず不正です。byteを返す場合の定数範囲やbooleanの条件も、戻り値の宣言型と式の型を比較して検証します。
図解
重要ポイント
- 戻り値は表示とは別。
- voidの呼出しを値として代入できない。
- 値を返すメソッドは正常に終わる経路で値を返す。
- returnは現在のメソッドから呼出し元へ戻る。
間違えやすい点
- 戻り値を使わなければ必ずコンパイルエラーになると思わない。
- voidに数値を返さない。
- コンパイル可能なnull返却を安全な参照利用と混同しない。
用語解説
- 戻り値
- 呼出し元へ返す式の値。
- void
- 値を返さないことを表すメソッドの結果指定。
- return
- 現在のメソッドから戻る文。
- 到達不能
- 実行が到達できず、規則によりコンパイルが拒否される文の状態。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。