質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.11%

JavaSliver試験(例外処理)

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 790

score -48

package chapter8;

public class Main {

    public static void main(String[] args) {
        int result = sample();
        System.out.println(result);
    }

    private static int sample() {
        int val = 0;
        try {
            String array[] = { "A", "B", "C" };
            System.out.println(array[3]);

        } catch (RuntimeException e) {
            val = 10;
            return val;
        } finally {
            val += 10;
        }
        return val;
    }
}

この答えは10です。解説には以下の様にあります。
戻り値のための変数とメソッド内で使用されているvalは違う

動きをデバッグで確認しました。sample()メソッド内の初めにブレークポイントを置きました。
System.out.println(result)に処理が移る直前まではsample()内の全てのvalの値は20だったのですが、System.out.println(result)に遷移した瞬間から10になります。

なぜでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2019/06/16 18:22

    参照渡しと値渡しの違いを覚えましょうって話かな。
    解説はそれだけじゃないはずですよ

    キャンセル

  • m.ts10806

    2019/06/16 18:34

    タイトルは要件のみを記載してください

    キャンセル

回答 2

checkベストアンサー

+2

例外が発生してcatch節に入り、returnが実行された時点で、メソッドとしての返り値が10で確定します。それ以降ローカル変数をいくらいじっても、確定した返り値に影響はありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/16 18:52

    その説明だと参照型変数の内部をいじっても変わらないようにとられる気がするけど

    キャンセル

  • 2019/06/16 19:08

    それは思ったけど、それに言及するとかえって混乱を呼びそうで…

    キャンセル

  • 2019/06/17 19:27

    「プリミティブは」と入れておけば良いのではないでしょうか.

    キャンセル

  • 2019/06/17 19:34

    jimbe
    +=で代入できる物全てが同じ結果になる

    まあ確認してないけどインクリメント、デクリメントなら反映されるかもね?

    キャンセル

+2

戻り値のための変数とメソッド内で使用されているvalは違う 
...
なぜでしょうか。

このプログラムの例外シナリオ

  • array[3] ここで添字が範囲外
  • ArrayIndexOutOfBoundsException (RuntimeException)が発生する
  • catch に処理が移る
  • val = 10;
  • return val; <— 1)
  • val += 10; <— 2) finally で加算される
  • return <— 3) 戻りを実行する

eclipse のデバッガで変数を追うと、val の値が 10 から 20 に変わったあとで return され、main に戻り、result の値を見ると 10 。return されたのは 20 だと思ったのに。上の 1), 2), 3) デバッガで追った動作に何か隠された処理があるのだろうか。

バイトコード

わからないときはバイトコードを調べましょう。

javap -p -v -c chapter8.Main

sample()のローカル変数は次のように対応しています。

  • 0 val
  • 1 arrayの参照
  • 2 RuntimeExceptionの参照
  • 3 戻り値用の無名のローカル変数 (例外処理の時だけ追加され使われます)

ローカル変数テープルに 3 は存在しませんが、メソッドのローカル変数が 4 個なのでコードを読み確認します。locals=4, args_size=0

例外処理のコードを読みます。

34: astore_1
35: bipush        10
37: istore_0
38: iload_0
39: istore_3
40: iinc          0, 10
43: iload_3
44: ireturn

(34 スタックのトップにある参照をローカル変数 1 (array)に格納)
35 オペランドスタックに10をプッシュ
36 ローカル変数 0 (val) に(10)を格納 <— val = 10
37 オペランドスタックに、ローカル変数 0 (val) の値、10 をロード
38 ローカル変数 3 (戻り値) に (10) を格納 <— 戻り値をいったん退避
40 ローカル変数 0 (val) に 10 加算。20 <- finally の加算 val += 10
43 オペランドスタックに、ローカル変数 3 (戻り値)  10 をロード
44 オペランドスタックのトップを戻り値としてsampleからリターン

戻り値をいったんローカル変数 3 に退避しておき、finally の val += 10 を実行しますが、val は戻り値として使わず、ローカル変数 3 を戻り値として使います。これが「戻り値のための変数とメソッド内で使用されているvalは違う」の意味。

例外処理のなかで return が記述されているので、直前の val の値を確定した戻り値として退避したのです。

デバッガで見ることができる変数は、val, RuntomeException のみ。退避動作もデバッガでは省略されています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/18 20:30

    これ仕様がおかしくないでしょうか。これを考えた人は頭が変だと思うのはわたしだけ?

    キャンセル

  • 2019/06/18 22:01

    「ちゃんと演算子とか諸々の仕組み分かってますか?」って確認するための試験問題なんだから、仕様がどうこう言うのはナンセンスだと思います。

    キャンセル

  • 2019/06/18 22:30

    そうね。いろいろ思うことがあるけれど、いずれどこかで。コメントありがとう。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る