第8回Javaゼミ

Download Report

Transcript 第8回Javaゼミ

第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)