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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1298閲覧

JavaSliver試験(例外処理)

Chandler_Bing

総合スコア673

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2019/06/16 09:04

java

1package chapter8; 2 3public class Main { 4 5 public static void main(String[] args) { 6 int result = sample(); 7 System.out.println(result); 8 } 9 10 private static int sample() { 11 int val = 0; 12 try { 13 String array[] = { "A", "B", "C" }; 14 System.out.println(array[3]); 15 16 } catch (RuntimeException e) { 17 val = 10; 18 return val; 19 } finally { 20 val += 10; 21 } 22 return val; 23 } 24}

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

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

なぜでしょうか。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/06/16 09:22

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

2019/06/16 09:34

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

回答2

0

戻り値のための変数とメソッド内で使用されている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) デバッガで追った動作に何か隠された処理があるのだろうか。

バイトコード

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

bash

1javap -p -v -c chapter8.Main 2

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

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

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

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

byte

134: astore_1 235: bipush 10 337: istore_0 438: iload_0 539: istore_3 640: iinc 0, 10 743: iload_3 844: 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/16 11:42

xebme

総合スコア1081

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xebme

2019/06/18 11:30

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

2019/06/18 13:01

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

2019/06/18 13:30

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

0

ベストアンサー

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

投稿2019/06/16 09:18

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/06/16 09:52

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

2019/06/16 10:08

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

2019/06/17 10:27

「プリミティブは」と入れておけば良いのではないでしょうか.
退会済みユーザー

退会済みユーザー

2019/06/17 10:34

jimbe +=で代入できる物全てが同じ結果になる まあ確認してないけどインクリメント、デクリメントなら反映されるかもね?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問