第8回Javaゼミ 8.1 8.2 8.3 8.4 8.6 例外処理 catchブロックの検索 throwステートメント 例外とエラークラス 独自の例外 2006/06/07 神津 健太 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); } } 表示されるメッセージ 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) このメッセージからは11行目で算術例外オブジェクトが生成されていることが わかる。この例外は、例外処理メカニズムによって処理される。 例外に関する情報が表示され、アプリケーションの実行が停止される。 8.1 例外処理(2) プログラムの実行中に発生した例外を、ユーザーの用意した処理ルーチンで 処理することができる。 try{ //tryブロック } tryブロック 例外の発生を監視するコードを記述。 このコードの実行中に問題が起こった場合、 例外 が投げられる。 catch(ExceptionType1 param1){ //例外処理ブロック } catch(ExceptionType2 param2){ //例外処理ブロック } ・ ・ catchブロック tryブロック内のコード実行中に問題発生した場合、 実行を停止し、例外処理できるcatchブロックを検索 する。例外オブジェクトの種類がCatchブロックのパラ メータと一致した場合、その処理が実行される。 paramNは、発生した問題に関する情報を格納したオ ブジェクト。 ・ catch(ExceptionTypeN paramN){ //例外処理ブロック } finally{ //finallyブロック } finallyブロック catchブロックが終わるとfinnalyに移行する。 必ず finallyブロックを実行するようにオブジェクトコードが 生成されるのでTryブロックが正常に終わるとfinnaly ブロックが実行される。tryブロックにreturnがあっても 戻る前に必ず実行される。 8.1 例外処理(3) 例外処理の例 catch(NumberFormatException e){ class Divider{ System.out.println("NumberFormatException"); public static void main(String args[]){ } try{ finally{ System.out.println("Before Division"); System.out.println("Finally block"); 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"); } 8.1 例外処理(4) 実行結果 >java Divider >java Divider 1 0 Before Division Before Division ArrayIndexOutOfBoundsException ArithmeticException Finally block Finally block >java Divider 1 >java Divider 1 1 Before Division Before Division ArrayIndexOutOfBoundsException 1 Finally block After Division Finally block 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{ try{ System.out.println("Before b"); System.out.println("Before a"); b(); a(); System.out.println("After b"); System.out.println("After a"); } } catch(ArithmeticException e){ catch(Exception e){ System.out.println("a: " + e); System.out.println("main: " + e); } } finally{ finally{ System.out.println("a: finally"); System.out.println("main: finally"); } } } } 8.2 catchブロックの検索(3) public static void b(){ public static void c(){ try{ try{ System.out.println("Before c"); System.out.println("Before d"); c(); d(); System.out.println("After c"); System.out.println("After d"); } } catch(ArrayIndexOutOfBoundsException e){ catch(NumberFormatException e){ System.out.println("b: " + e); System.out.println("c: " + e); } } finally{ finally{ System.out.println("b: finally"); System.out.println("c: finally"); } } } } 8.2 catchブロックの検索(4) 実行結果 public static void d(){ try{ Before b array[10] = 10; Before c } Before d catch(ClassCastException e){ d: finally c: finally } b: java.lang.ArrayIndexOutOfBoundsException: 10 finally{ b: finally System.out.println("d: finally"); } } Before a int array[] = new int[4]; System.out.println("d: " + e); } >java CatchSearch 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{ try{ int i = 1; System.out.println("Befor a"); int j = 0; a(); System.out.println("Befor Division"); System.out.println("After a"); System.out.println(i/j); } System.out.println("After Division"); catch(ArithmeticException e){ } System.out.println("main: " + e); catch(ArithmeticException e){ } System.out.println("a: " + e); finally{ throw e; System.out.println("main: finally"); } } 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{ try{ System.out.println("Befor throw statement"); System.out.println("Befor a"); throw new ArithmeticException(); a(); } System.out.println("After a"); catch(ArithmeticException e){ } System.out.println("a: " + e); catch(ArithmeticException e){ } System.out.println("main: " + e); finally{ } System.out.println("a: finally"); finally{ } System.out.println("main: 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クラス 全ての例外、エラークラスのスーパークラス。CatchブロックにはTrowble型のパラ メータが必ず1つなければならない。コンストラクタは次のとおり。 Throwble() Throwble(String message) message:問題を通知する文字列のメッセージ Throwbleクラスのメソッド ・ String getMessage() コンストラクタから提供された文字列を返す。 ・ void printStackTrace() 問題が発生した時点でのスタック情報を表示する。 スタック情報を標準出力に表示。 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(){ public static void main(String args[]){ try{ int i = 1; try{ int j = 0; a(); System.out.println(i/j); } } catch(ArithmeticException e){ catch(NullPointerException e){ e.printStackTrace(); e.printStackTrace(); } } } } } 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[]){ throws ClassNotFoundException{ a(); c(); } } public static void a(){ public static void c() try{ throws ClassNotFoundException{ b(); Class cls = Class.forName("java.lang.Integer") } catch(ClassNotFoundException e){ ; System.out.println(cls.getName()); e.printStackTrace(); 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には、独自の例外クラスを作成する機能がある。 このようなクラスはExceptionのサブクラスとして作成する。 例外のインスタンスを投げるには、throwsステートメントを使う。 import java.util.*; static void b() throws ExceptionA{ try{ class ExceptionSubclass{ c(); public static void main(String args[]){ } a(); catch(ExceptionB e){ } e.printStackTrace(); static void a(){ try{ b(); } static void c() throws ExceptionA, ExceptionB{ } Random random = new Random(); catch(Exception e){ int i = random.nextInt(); e.printStackTrace(); } } } if(i % 2 == 0){ throw new ExceptionA("We have a problem"); } 8.6 独自の例外(2) else{ class ExceptionB extends Exception{ throw new ExceptionB("We have a big problem"); public ExceptionB(String message){ super(message); } } } } } class ExceptionA extends Exception{ public ExceptionA(String message){ super(message); } } 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)
© Copyright 2024 ExpyDoc