8.1 例外処理 8.2 catchブロックの検索 8.3 throwステートメント 8.4 例外とエラークラス 8.6 独自の例外 第8回Javaゼミ 8.1 例外処理 8.2 catchブロックの検索 8.3 throwステートメント 8.4 例外とエラークラス 8.6 独自の例外 2006/06/07 神津 健太
8.1 例外処理(1) 例外の例 表示されるメッセージ このメッセージからは11行目で算術例外オブジェクトが生成されていることが 8.1 例外処理(1) 例外の例 class DivideByZero{ public static void main(String args[]){ a(); } static void a(){ b(); static void b(){ int i = 1; int j = 0; System.out.println(i/j); このメッセージからは11行目で算術例外オブジェクトが生成されていることが わかる。この例外は、例外処理メカニズムによって処理される。 例外に関する情報が表示され、アプリケーションの実行が停止される。 表示されるメッセージ Exception in thread "main" java.lang.ArithmeticException: / by zero at DivideByZero.b(DivideByZero.java:11) at DivideByZero.a(DivideByZero.java:6) at DivideByZero.main(DivideByZero.java:3)
8.1 例外処理(2) プログラムの実行中に発生した例外を、ユーザーの用意した処理ルーチンで処理することができる。 8.1 例外処理(2) プログラムの実行中に発生した例外を、ユーザーの用意した処理ルーチンで処理することができる。 try{ //tryブロック } catch(ExceptionType1 param1){ //例外処理ブロック catch(ExceptionType2 param2){ ・ catch(ExceptionTypeN paramN){ finally{ //finallyブロック tryブロック 例外の発生を監視するコードを記述。 このコードの実行中に問題が起こった場合、 例外が投げられる。 catchブロック tryブロック内のコード実行中に問題発生した場合、実行を停止し、例外処理できるcatchブロックを検索する。例外オブジェクトの種類がCatchブロックのパラメータと一致した場合、その処理が実行される。 paramNは、発生した問題に関する情報を格納したオブジェクト。 finallyブロック catchブロックが終わるとfinnalyに移行する。 必ずfinallyブロックを実行するようにオブジェクトコードが生成されるのでTryブロックが正常に終わるとfinnalyブロックが実行される。tryブロックにreturnがあっても戻る前に必ず実行される。
8.1 例外処理(3) 例外処理の例 class Divider{ 8.1 例外処理(3) 例外処理の例 class Divider{ public static void main(String args[]){ try{ System.out.println("Before Division"); int i = Integer.parseInt(args[0]); int j = Integer.parseInt(args[1]); System.out.println(i/j); System.out.println("After Division"); } catch(ArithmeticException e){ System.out.println("ArithmeticException"); catch(ArrayIndexOutOfBoundsException e){ System.out.println("ArrayIndexOutOfBoundsException"); catch(NumberFormatException e){ System.out.println("NumberFormatException"); } finally{ System.out.println("Finally block");
8.1 例外処理(4) 実行結果 >java Divider >java Divider 1 0 Before Division 8.1 例外処理(4) 実行結果 >java Divider Before Division ArrayIndexOutOfBoundsException Finally block >java Divider 1 >java Divider 1 0 Before Division ArithmeticException Finally block >java Divider 1 1 1 After Division
8.2 catchブロックの検索(1) catchブロックの検索はtryブロックの直後の1つ目から開始される。これは一致するまで行われる。 例外オブジェクトに対応するcatchブロックがない場合、他のtryブロックのcatchブロックが検索される。 それでも見つからない場合は、さらにスタックをさかのぼってメソッドが検索される。 main()メソッドまでさかのぼっても見つからない場合は、既定の例外処理が呼び出され、例外メッセージを表示して終わる。
8.2 catchブロックの検索(2) class CatchSearch{ public static void a(){ public static void main(String args[]){ try{ System.out.println("Before a"); a(); System.out.println("After a"); } catch(Exception e){ System.out.println("main: " + e); finally{ System.out.println("main: finally"); public static void a(){ try{ System.out.println("Before b"); b(); System.out.println("After b"); } catch(ArithmeticException e){ System.out.println("a: " + e); finally{ System.out.println("a: finally");
8.2 catchブロックの検索(3) public static void b(){ public static void c(){ try{ System.out.println("Before c"); c(); System.out.println("After c"); } catch(ArrayIndexOutOfBoundsException e){ System.out.println("b: " + e); finally{ System.out.println("b: finally"); public static void c(){ try{ System.out.println("Before d"); d(); System.out.println("After d"); } catch(NumberFormatException e){ System.out.println("c: " + e); finally{ System.out.println("c: finally");
8.2 catchブロックの検索(4) 実行結果 public static void d(){ try{ int array[] = new int[4]; array[10] = 10; } catch(ClassCastException e){ System.out.println("d: " + e); finally{ System.out.println("d: finally"); >java CatchSearch Before a Before b Before c Before d d: finally c: finally b: java.lang.ArrayIndexOutOfBoundsException: 10 b: finally After b a: finally After a main: finally
8.3 throwステートメント(1) throwステートメントを使って、プログラム内で明示的に例外を生成することができる。 throw object; objectはjava.lang.Throwble型でなければエラーになる。 catchブロック内部では、引数として例外オブジェクトを投げることができる。 catch(ExceptionType param){ ・ throw param; } 新しい例外オブジェクトを作成して投げるには、 throw new ExceptionType(args);
8.3 throwステートメント(2) lass ThrowDemo{ public static void a(){ public static void main(String args[]){ try{ System.out.println("Befor a"); a(); System.out.println("After a"); } catch(ArithmeticException e){ System.out.println("main: " + e); finally{ System.out.println("main: finally"); public static void a(){ try{ int i = 1; int j = 0; System.out.println("Befor Division"); System.out.println(i/j); System.out.println("After Division"); } catch(ArithmeticException e){ System.out.println("a: " + e); throw e; finally{ System.out.println("a: finally");
8.3 throwステートメント(3) 実行結果 >java ThrowDemo Befor a Befor Division a: java.lang.ArithmeticException: / by zero a: finally main: java.lang.ArithmeticException: / by zero main: finally a()メソッド内に、この例外に該当するcatchブロックがある。このブロックで引数として受け取った例外オブジェクトを投げる。 そのため、該当するcatchブロックの検索がmain()メソッドでも継続される。main()メソッドでも該当するcatchブロックがあり、ここで例外処理が完了する。
8.3 throwステートメント(4) class ThrowDemo2{ public static void a(){ public static void main(String args[]){ try{ System.out.println("Befor a"); a(); System.out.println("After a"); } catch(ArithmeticException e){ System.out.println("main: " + e); finally{ System.out.println("main: finally"); public static void a(){ try{ System.out.println("Befor throw statement"); throw new ArithmeticException(); } catch(ArithmeticException e){ System.out.println("a: " + e); finally{ System.out.println("a: finally");
8.3 throwステートメント(5) 実行結果 >java ThrowDemo2 Befor a Befor throw statement a: java.lang.ArithmeticException a: finally After a main: finally a()メソッド内のtryブロックにthrowステートメントがある。ここで例外を作成し、直後のcatchブロックで例外処理が完了する。 throwステートメントでは、new演算子を使って、ArithmeticExceptionオブジェクトを作成している。
8.4 例外とエラークラス(1) Throwbleクラス 8.4 例外とエラークラス(1) Throwbleクラス 全ての例外、エラークラスのスーパークラス。CatchブロックにはTrowble型のパラメータが必ず1つなければならない。コンストラクタは次のとおり。 Throwble() Throwble(String message) message:問題を通知する文字列のメッセージ Throwbleクラスのメソッド ・ String getMessage() コンストラクタから提供された文字列を返す。 ・ void printStackTrace() 問題が発生した時点でのスタック情報を表示する。 スタック情報を標準出力に表示。
8.4 例外とエラークラス(2) Errorクラス Exceptionクラス RuntimeExceptionクラス 8.4 例外とエラークラス(2) Errorクラス Throwbleクラスを拡張する。JVMで検出される可能性がある重大な問題を表す サブクラスが10以上ある。 Exceptionクラス Throwbleクラスを拡張する。実行時に発生する可能性があるさまざまな問題を 表すサブクラスがある。コンストラクトは次のとおり。 Exception() Exception(String message) RuntimeExceptionクラス Exceptionクラスの最も重要なサブクラス。プログラムの実行中に発生する頻度 が高い問題を表す。コンストラクタは次の通り。 RuntimeException() RuntimeException(String message)
8.4 例外とエラークラス(3) class PSTDemo{ public static void a(){ 8.4 例外とエラークラス(3) class PSTDemo{ public static void main(String args[]){ try{ a(); } catch(ArithmeticException e){ e.printStackTrace(); public static void a(){ try{ int i = 1; int j = 0; System.out.println(i/j); } catch(NullPointerException e){ e.printStackTrace();
8.4 例外とエラークラス(4) 実行結果 >java PSTDemo 8.4 例外とエラークラス(4) 実行結果 >java PSTDemo java.lang.ArithmeticException: / by zero at PSTDemo.a(PSTDemo.java:14) at PSTDemo.main(PSTDemo.java:4) ArithmeticException例外が発生した時点で、スタックには各メソッドの情報が積まれている。この例外はmain()メソッドで例外処理される。そのとき、 printStackTrace()メソッドが呼び出され、例外発生時のスタック情報が表示される。
8.5 throwsステートメント(1) 呼び出し元に対して例外を投げる可能性があるメソッドの場合、どの例外が投げられるのかを明示しておくと便利。 → コンストラクタ内のthrowsステートメントを使う。次のような構文になる。 consModifiers clsName(cparam) throws exceptions{ // コンストラクタの本体 } メソッドの宣言では次のようになる。 mthModifiers rtype mthName(mparam) throws exceptions{ // メソッドの本体
8.5 throwsステートメント(2) class ThrowsDemo{ public static void b() public static void main(String args[]){ a(); } public static void a(){ try{ b(); catch(ClassNotFoundException e){ e.printStackTrace(); public static void b() throws ClassNotFoundException{ c(); } public static void c() Class cls = Class.forName("java.lang.Integer"); System.out.println(cls.getName()); System.out.println(cls.isInterface());
8.5 throwsステートメント(3) 実行結果 >java ThrowsDemo java.lang.Integer false c()メソッドではClassクラスのforName()メソッドを呼び出す。このときClassNotFoundException例外が投げられる可能性がある。 そのためc()メソッドではthrowsステートメントを記述して、 ClassNotFoundException例外が投げられる可能性があることを宣言している。 b()メソッドも同様。 a()メソッドでは例外を捕獲するのでthrowsステートメントは不要。
8.6 独自の例外(1) Javaには、独自の例外クラスを作成する機能がある。 8.6 独自の例外(1) Javaには、独自の例外クラスを作成する機能がある。 このようなクラスはExceptionのサブクラスとして作成する。 例外のインスタンスを投げるには、throwsステートメントを使う。 import java.util.*; class ExceptionSubclass{ public static void main(String args[]){ a(); } static void a(){ try{ b(); catch(Exception e){ e.printStackTrace(); static void b() throws ExceptionA{ try{ c(); } catch(ExceptionB e){ e.printStackTrace(); static void c() throws ExceptionA, ExceptionB{ Random random = new Random(); int i = random.nextInt(); if(i % 2 == 0){ throw new ExceptionA("We have a problem");
8.6 独自の例外(2) else{ class ExceptionB extends Exception{ 8.6 独自の例外(2) else{ throw new ExceptionB("We have a big problem"); } class ExceptionA extends Exception{ public ExceptionA(String message){ super(message); class ExceptionB extends Exception{ public ExceptionB(String message){ super(message); }
8.6 独自の例外(3) 実行結果 >java ExceptionSubclass 8.6 独自の例外(3) 実行結果 >java ExceptionSubclass ExceptionB: We have a big problem at ExceptionSubclass.c(ExceptionSubclass.java:30) at ExceptionSubclass.b(ExceptionSubclass.java:17) at ExceptionSubclass.a(ExceptionSubclass.java:9) at ExceptionSubclass.main(ExceptionSubclass.java:5) ExceptionAクラスとExceptionBクラスはExceptionクラスを拡張する。 c()メソッドでは無作為な値を作成し、A,Bどちらの例外を投げるか決定する。 b()メソッドのthrowsステートメントにはExceptionAのみ記述。ExceptionB例外はメソッド内のcatchブロックで処理される。 a()メソッドはすべての例外を処理するcatchブロックがあるので、throwssテートメントの記述は不要。
練習問題(1) 整数値のみの除算を行うプログラムを作りなさい。 ただし、引数が不足している場合、第2引数が0の場合、引数が整数値ではない場合は、それぞれ任意のエラーメッセージが表示されるようにしなさい。 実行結果例 >java IntDiv 引数が足りません >java IntDiv 1 0 第2引数が0では計算できません >java IntDiv 1 0.5 整数値しか計算できません >java IntDiv 1 1 1/1=1
練習問題(2) 年齢を入力すると、「平成生まれ」、「昭和生まれ」、「大正生まれ」かを表示するプログラムを作りなさい。(大正以前の人はいないものとする。)また、問題1と同様に任意のエラーメッセージも表示させなさい。 ただし、System.out.println()およびprint()は使わないこと。 独自の例外を作成してそれを利用すること。 注) 大正:~1926年 昭和:1927~1988年 平成:1989年~ とする。 実行結果例 >java Nendai 10 Exception in thread "main" ExceptionH: 平成生まれ at Nendai.main(Nendai.java:10)