JavaSliver試験(例外処理)
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 790
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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
例外が発生してcatch節に入り、returnが実行された時点で、メソッドとしての返り値が10で確定します。それ以降ローカル変数をいくらいじっても、確定した返り値に影響はありません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+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 のみ。退避動作もデバッガでは省略されています。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.11%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
asahina1979
2019/06/16 18:22
参照渡しと値渡しの違いを覚えましょうって話かな。
解説はそれだけじゃないはずですよ
m.ts10806
2019/06/16 18:34
タイトルは要件のみを記載してください