2023.02.20
予約語
finally句
ここでは、例外発生の有無に関わらず、実行する処理を記述するfinallyブロックについて解説します。
以下のように、記述します。
try { 実行する処理1; 実行する処理2; : 実行する処理n; } catch(例外クラス 変数名) { 例外が発生したときの処理; 例外が発生したときの処理; } finally { 最後に実行する処理; }
finallyを使わない場合 その1
まず、finallyブロックが無いtry { ... } catch { ... }についてについて解説します。
ここでは、「最後に実行する処理」をtryブロックとcatchブロックの外に記述します。
try { 実行する処理1; 実行する処理2; : 実行する処理n; } catch(例外クラス 変数名) { 例外が発生したときの処理; } 最後に実行する処理;
上記のソースコードのtryブロック内の「実行する処理1」から「実行する処理n」のどこかで例外が発生した場合、失敗した処理より後の処理は実行されずに、catchブロック内の「例外が発生したときの処理」に移行します。例えば、「実行する処理2」で例外が発生した場合、「実行する処理3」からの処理は実行されずに、catchブロックの処理に移行します。
このソースコードの場合、tryブロック内で例外が発生しない場合でも、発生した場合でも「最後に実行する処理」が実行されます。
FinallySample1.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020
// finally説明用のサンプル1 // finallyブロックはありません。 public class FinallySample1 { public static void main(String[] args) { try { int a = 5; // 割られる数 a int b = 0; // 割る数 b int c = a / b; // 割り算の結果をcに代入 System.out.println( c ); // 割り算の結果を出力 } catch ( ArithmeticException e ) { System.out.println( "エラー(" + e + ")" ); // エラー内容を出力 } // 最後に実行する処理 System.out.println( "最後に実行する処理" ); } }
FinallySample1.javaをコンパイル(ソースコードがANSIの場合)
javac -encoding sjis FinallySample1.java
FinallySample1を実行
java FinallySample1
FinallySample1の出力結果
エラー(java.lang.ArithmeticException: / by zero) 最後に実行する処理
finallyを使わない場合 その2
以下のソースコードの場合はどうでしょうか?
try {
実行する処理1;
実行する処理2;
:
実行する処理n;
}
catch(例外クラス 変数名) {
例外が発生したときの処理;
return;
}
最後に実行する処理;
tryブロック内で例外が発生しない場合は、tryブロックを抜けて「最後に実行する処理」が実行されます。
例外が発生した場合は、catchブロックに処理が移行します。catchブロック内にreturn文があるので、そのreturn文以降の処理が実行されません。よって、「最後に実行する処理」も実行されません。
FinallySample2.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023
// finally説明用のサンプル2 // finallyブロックはありません。 public class FinallySample2 { public static void main(String[] args) { try { int a = 5; // 割られる数 a int b = 0; // 割る数 b int c = a / b; // 割り算の結果をcに代入 System.out.println( c ); // 割り算の結果を出力 } catch ( ArithmeticException e ) { System.out.println( "エラー(" + e + ")" ); // エラー内容を出力 // mainメソッドを抜ける return; } // 最後に実行する処理 System.out.println( "最後に実行する処理" ); } }
FinallySample2.javaをコンパイル(ソースコードがANSIの場合)
javac -encoding sjis FinallySample2.java
FinallySample2を実行
java FinallySample2
FinallySample2の出力結果
エラー(java.lang.ArithmeticException: / by zero)
finallyを使わない場合 その3
以下は、あまり良くないソースコードの書き方で、tryブロックとcatchブロックの中の両方に「最後に実行する処理」を記述したものです。
この書き方の場合、例外が発生しなくても発生しても「最後に実行する処理」が実行されますが、同じ処理を複数回記述しているので、良いとはいえません。
try {
実行する処理1;
実行する処理2;
:
実行する処理n;
最後に実行する処理;
}
catch(例外クラス 変数名) {
例外が発生したときの処理;
最後に実行する処理;
return;
}
FinallySample3.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026
// finally説明用のサンプル3 // finallyブロックはありません。 public class FinallySample3 { public static void main(String[] args) { try { int a = 5; // 割られる数 a int b = 0; // 割る数 b int c = a / b; // 割り算の結果をcに代入 System.out.println( c ); // 割り算の結果を出力 // 最後に実行する処理 System.out.println( "最後に実行する処理" ); } catch ( ArithmeticException e ) { System.out.println( "エラー(" + e + ")" ); // エラー内容を出力 // 最後に実行する処理 System.out.println( "最後に実行する処理" ); // mainメソッドを抜ける return; } } }
FinallySample3.javaをコンパイル(ソースコードがANSIの場合)
javac -encoding sjis FinallySample3.java
FinallySample3を実行
java FinallySample3
FinallySample3の出力結果
エラー(java.lang.ArithmeticException: / by zero) 最後に実行する処理
finallyを使う
次に、finallyブロックを記述したtry { ... } catch { ... } finally { ... }についてについて解説します。
ここでは、「最後に実行する処理」をfinallyブロックに記述します。
try {
実行する処理1;
実行する処理2;
:
実行する処理n;
}
catch(例外クラス 変数名) {
例外が発生したときの処理;
例外が発生したときの処理;
return;
}
finally {
最後に実行する処理;
}
このソースコードは、tryブロックで例外の発生の有無に関わらす「最後に実行する処理」が実行されます。
catchブロックの中に、return文があるのでメソッドを抜けます。finallyブロックの中の処理は、このreturn文に関係なく実行されます。
FinallySample4.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024
// finally説明用のサンプル4 // finallyブロックで「最後に実行する処理」を実行します。 public class FinallySample4 { public static void main(String[] args) { try { int a = 5; // 割られる数 a int b = 0; // 割る数 b int c = a / b; // 割り算の結果をcに代入 System.out.println( c ); // 割り算の結果を出力 } catch ( ArithmeticException e ) { System.out.println( "エラー(" + e + ")" ); // エラー内容を出力 // mainメソッドを抜ける return; } finally { // 最後に実行する処理 System.out.println( "最後に実行する処理" ); } } }
FinallySample4.javaをコンパイル(ソースコードがANSIの場合)
javac -encoding sjis FinallySample4.java
FinallySample4を実行
java FinallySample4
FinallySample4の出力結果
エラー(java.lang.ArithmeticException: / by zero) 最後に実行する処理
finallyでやってはいけないこと
finallyブロック内で、制御が外へ移行する処理が記述できません。
以下がその例です。
finally {
return;
}
finally {
break;
}
finally {
continue;
}
finally { System.exit( 0 ); }
FinallySample5.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034
// finally説明用のサンプル5 // finallyブロックにreturn文を記述しています。(お勧めしません) public class FinallySample5 { private static String FinallyTest() { try { int a = 5; // 割られる数 a int b = 0; // 割る数 b int c = a / b; // 割り算の結果をcに代入 System.out.println( c ); // 割り算の結果を出力 } catch ( ArithmeticException e ) { System.out.println( "エラー(" + e + ")" ); // エラー内容を出力 // メソッドを抜ける return "catchブロックのreturn実行"; } finally { // 最後に実行する処理 return "finallyブロックのreturn実行"; } } public static void main(String[] args) { String ans = FinallyTest(); // 結果をコンソール出力 System.out.println( ans ); } }
FinallySample5.javaをコンパイル(ソースコードがANSIの場合)
javac -encoding sjis FinallySample5.java
FinallySample5を実行
java FinallySample5
FinallySample5の出力結果
エラー(java.lang.ArithmeticException: / by zero) finallyブロックのreturn実行