try-catch-finallyのメモ


try-catch-finallyの学習メモです。

finally中に、returnを利用する

例:

    public static void main(String[] args) {
        System.out.println("result: " + getValue());
    }
    private static int getValue() {
        int num = 0;
        try {
            num++;
            System.out.println("try句が実行されました。");
          ...
            return num;
        } catch (Exception e) {
            // do something
        } finally {
            num++;
            System.out.println("finally句が実行されました。");
            return num;
        }
    }

実行結果:
try句が実行されました。
finally句が実行されました。
result: 2

もしtryとfinallyの中に、両方returnが利用している場合、tryのreturnを無視して、finallyのreturnの値を返却します。
なので、returnを利用する際、基本は、メソッドの最後に書きます。

例:

    public static void main(String[] args) {
        System.out.println("result: " + getValue());
    }
    private static int getValue() {
        int num = 0;
        try {
            num++;
            ...
        } catch (Exception e) {
            // do something
        } finally {
            // do something
        }
        return num;
    }
実行結果:
result: 1

finally中にソースが実行されない

例:

    public static void main(String[] args) {
        System.out.println("result: " + getValue());
    }
    private static int getValue() {
        int num = 0;
        try {
            System.out.println("try句が実行されました。");
            return num;
        } finally {
            System.out.println("finally句が実行されました。");
            num++;
        }
    }
実行結果:
try句が実行されました。
finally句が実行されました。
result: 0

この例から、finallyのソースが実行されてないわけではないです。出力の順番で1ではなく、0が出力されるように見えます。
原因は、finallyのコンパイル仕組みに関わっているため、以下の資料を参照してください。
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.13

ここも、returnを利用する際、メソッドの最後に書くことが大事です。

finally中のソースが最後で実行する

例:

    public static void main(String[] args) {
        execErr();
    }
    private static void execErr() {
        try {
            System.out.println("try句が実行されました。");
            throw new RuntimeException();
        } catch (RuntimeException e) {
            System.out.println("catch句が実行されました。");
        } finally {
            System.out.println("finally句が実行されました。");
        }
    }

実行結果:
try句が実行されました。
catch句が実行されました。
finally句が実行されました。

ただ、catch文の中に、例外を出力する処理がある場合、finallyを実行した後、例外をスローします。

例:

    public static void main(String[] args) {
        execErr();
    }
    private static void execErr() {
        try {
            System.out.println("try句が実行されました。");
            throw new RuntimeException();
        } catch (RuntimeException e) {
            System.out.println("catch句が実行されました。");
       e.printStackTrace();
        } finally {
            System.out.println("finally句が実行されました。");
        }
    }

実行結果:
try句が実行されました。
catch句が実行されました。
finally句が実行されました。
java.lang.RuntimeException
    at com.sample.StudyTryCatch.execErr(StudyTryCatch.java:11)
    at com.sample.StudyTryCatch.main(StudyTryCatch.java:6)。