例外(exception)とは何か

例外処理
Exception Handling
•
•
•
•
•
•
•
例外(exception)とは何か
例外処理(exception handling)とは何か
メソッドの実行時基本流れ図
例外処理の基本構造 – try/catch/finally blocks
Error/Exception/Runtime_Exception
Throwableクラスと例外クラスの定義
例外オブジェクト:例外スロー(throws, throw)
例外(exception)とは何か (What is the exception?)
(1)日常の例外
例外というのは、規則(規律)をまもらないということです。
例えば、私は毎日6時に起きます。けれども今週の日曜日は例外です。
(2)Java言語の例外
Java言語の例外は、Java言語の規則をまもらないのことです。
例えば、1)
配列の長さを超えた添え字で要素を参照しょうとした。
int a[] = new int[3]; //aの添字は、0から2までの整数です。
a[6] = 7;
Golden rule: errors occur
• コンパイル時エラー
Errors in compile
=>ArrayIndexOutOfBoundsException L61
• プログラムの実行時エラー(致命)
2) 割り算の分母は0になる場合。
Errors in program execution
-- serious error, con not recover
• プログラムの実行時例外(修復できる)
=>ArithmeticException L62
Exceptions in program execution
-- not serious error, can recover
3) ファイルをオープンしようとしたが、ファイルがない。
=>FileNotFoundException
Java言語の例外の例 (例外処理なし)
Example of Java exception without exception handling
配列の範囲を超える
ゼロによる割り算
public class arrayTest {
public class DivideByZero {
public static void main(String[] args) {
public static void main(String[] args) {
int[ ] a = new int[3];
System.out.println( quotient(3, 5));
System.out.println("a[2]に代入する");
System.out.println( quotient(3, 0));
a[2] = 8;
System.out.println( quotient(5, 6));
System.out.println("a[2]に代入した");
}
System.out.println("a[3]に代入する");
public static double quotient(int bunshi, int bunbo)
{
a[3] = 5;
return (double) bunshi / bunbo;
System.out.println("a[3]に代入した");
}
System.out.println("終了します");
}
}
}
実行結果:L61
ここで例外
(配列の範囲を越えた)
が起きる
ここで例外
実行結果:L62
(ゼロによる割り算)
が起きる
例外処理 Exception handling
例外処理とは、プログラム実行中のエラーを通知し、適切なエ
ラー処理が出来るようにする機構です。
(必ずしもエラーだけでなく、例外的な処理に利用されることも)
int[ ] a = new int[3];
a[2] = 8; //ok
a[3] = 5; //例外(ArrayIndexOutOfBoundsException)
// が発生する。
例外処理をされると
クラス
例外が起きる
かも知れない範
囲をtry{ }で囲む
例外処理の
プログラム
ArrayIndexOutOfBoundsException
int[ ] a = new int[3];
のインスタンスがスローされる
try {
....
キャッチする
a[3] = 5;
例外のクラス
....
} catch (ArrayIndexOutOfBoundsException e) {
キャッチした
System.out.println("例外" + e + "です");
例外オブジェクト
}
が入る
....
メソッドの実行時基本流れ図
メソッドの実行時エ
ラーがないとメソッド
が本流によって実行
されます。
method start
エラーがある
エラーなし
With error
例外オブジェクトの生成とスロー
(throw)
例外をRuntime Systemへ届ける
No error
本流
Runtime System
error
例外処理のは三つの
ステップがある。
• 例外オブジェクトのスロー
exception
• 例外のキャッチ
誰がこの例外を処理するを決める
• 例外の処理コード
例外のキャッチ
(catch)
決められないの場合
method end
例外処理のコード
Program end
or
Next method
Runtime Systemで誰
がこの例外を処理す
ることを決められない
とプログラム/メソッド
が中断されます。
例外処理の基本構造 (Exception handling mechanism)
try-catch-finally
try{
例外オブジェクトのスロー(投げる)
no exception
with exception
}
メソッドで、
•try { .... }の範囲を実行中にスローされた例外を
catch (... ) {.... }の(... )でキャッチして{.... }で処理する。
•例外がスローされなかった場合はcatch (... ) {.... }を
スキップ。
•一つのtryブロックに対しでは、0個以上catch
ブロークを置きます。
•finallyブロックはオプションです。そこにはリソース
を解放するためのコードを入れて置くのに最適な場所
です。
catch(exception1 e){
例外1の処理
}
catch(exception2 e){
例外2の処理
}
……
finally{
リソースの解放
}
Java言語の例外処理の例(Example of exception handing)
public class exceptionTest{
public static void main(String[] args) {
int[ ] a = new int[3];
try {
System.out.println(“a[2]に代入する”); a[2] = 8;
(配列の範囲を越えた)
System.out.println("a[2]に代入した");
がスローされる。
System.out.println(“a[3に代入する”); a[3] = 5;
キャッチした例
外オブジェクトを
出力する
ここで例外オブジェクト
throw
System.out.println("a[3]に代入した");
} catch (ArrayIndexOutOfBoundsException e) {
handling
System.out.println("例外" + e + "です");
} catch (Exception e) {
例外がスキップ
System.out.println("Exception" + e + "です");
ここで例外オブジェクト
(配列の範囲を越えた)
をキャッチする。
catch
} finally {
System.out.println("finally");
}
System.out.println("終了します");
}
}
実行結果: L61, L62
Throwableクラスと例外クラスの定義
Object
public class Throwable extends Object{
public Throwable();
public Throwable(String message);
Throwable
public String getMessage();
public void printStackTrace();
Exception
……
error
…
}
…
Runtime
Exception
public class Error extends Throwable{
public Error();
public Exception();
public Error(String s);
public Exception(String s);
}
…
public class Exception extends Throwable{
}
Other Exception – checked exception: must be caught and handled
ClassNotFoundException
RuntimeException – unchecked exception: may or
may not be caught and handled
……
IOException
ArithmeticException
AWTException
……
IndexOutOfBoundsException
public class DivideByZeroException extends Exception{
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
public DivideByZeroException()
{ super(“Attempted to divide by zero”);}
NegativeArraySizeException
……
}
ArrayIndexOutOfBoundsException
Runtime 例外クラスの例
java.lang.Object
|
+--java.lang.Throwable
|
+--java.lang.Exception
ArrayIndexOutOfBoundsException()
Constructs an ArrayIndexOutOfBoundsException with no
detail message.
ArrayIndexOutOfBoundsException(int index)
|
+--java.lang.RuntimeException
|
+--java.lang.IndexOutOfBoundsException
Constructs a new ArrayIndexOutOfBoundsException class
with an argument indicating the illegal index.
ArrayIndexOutOfBoundsException(String s)
|
+--java.lang.ArrayIndexOutOfBoundsException
try {
public String getMessage()
int a[] = new int[2];
Returns the errort message string of this throwable object.
a[4] = 10;;
public void printStackTrace()
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("exception: " + e.getMessage());
e.printStackTrace();
}
Constructs an ArrayIndexOutOfBoundsException class with
the specified detail message.
Prints this Throwable and its backtrace to the standard error
stream.
throws節とthrow文
throws節を使って、メソッドは指定した例外(オブジェクト)をスローする(生成す
る)可能性があるという宣言。 メソッドの中に、throw文で例外をスローします。
DivideByZeroException
を宣言します
public class DivideByZeroException extends Exception{
unchecked – ErrorとRuntimeExceptionのsub クラス
checked – 自分定義の例外クラス
public DivideByZeroException()
{ super(“Attempted to divide by zero”);}
コンストラクタ
}
public double quotient(int numerator, int denominator)
throws DivideByZeroException {
if (denominator == 0)
throw new DivideByZeroException();
return (double) numerator / denominator;
}
例外は二種類:
unchecked exception クラスは、メソッドに
throws節でこの例外をスローする可能性があ
るという宣言することが必要ない。
checked exception クラスは、メソッドにthrows
節でこの例外をスローする可能性があるとい
う宣言することが必要です。
このメソッドには
DivideByZeroExceptionをス
ローする可能性があるという
宣言
DivideByZeroExceptionを
ここでスローします
例外のキャーチと処理 (Example of exception handling)
public class DivideByZero {
public static void main(String[] args) {
try {
System.out.println( quotient(3, 5));
実行結果: L65
メソッド
quotient()を呼
び出し
System.out.println( quotient(3, 0));
System.out.println( quotient(5, 6));
}
ここでキャッチ
される
このメソッドは
catch (DivideByZeroException e) {
System.out.println( e);
キャッチした例外オ
ブジェクトを出力する
}
DivideByZeroExceptionをス
finallyブロック
なくでもよい
ローする可能性があるという
宣言
finally{System.out.println( “Finished !”);}
}
public double quotient(int numerator, int denominator) DivideByZeroExceptionを
throws DivideByZeroException {
if (denominator == 0)
ここでスローします
public DivideByZeroException()
return (double) numerator / denominator;
}
を宣言します
public class DivideByZeroException extends Exception{
throw new DivideByZeroException();
}
DivideByZeroException
{ super(“Attempted to divide by zero”);}
}
課題 (Exercise)
1
y = f(x) = 1/log(2x²-5x+2) for x=0~9を計算して、y[10]の
配列の中に結果を格納するアプレットのプログラム
(example)が左に与えられている。プログラムとそれに連
なったHTMLファイルをタイプした後、コンパイルして実
行せよ。テキストフィールドに0~9の数字を入力し、アプ
レットに何が表示されるのかを確認せよ。0未満、もしく
は9以上の数字を入力したとき、MS-DOSウィンドウに
どのような例外メッセージが表示されるか?例外が起
こったとき、ArrayIndexOutOfBoundsExceptionを
try/catchブロックを使ってメッセージ “You must enter an
integer from 0 to 9”が表示されるようにせよ。
2
整数以外の文字を入力したとき、どのような例外メッ
セージがMS-DOSウィンドウ上に表れるか?例外が
起こったとき、try/catchブロックを使用して
NumberFormatException をハンドルし、“You must enter
an integer. Other characters are illegal”というメッセージを
表示させよ。
3
"1"を入力したとき、特殊文字が表示される。これはlog()
関数の変数が負の値であるためである。レクチャーノー
トのDivideByZeroExceptionクラスを
参照して、このタイプの例外と一致する例外クラス
logOfNegativeValueを定義せよ。またメソッド(int x){...}
で例外をスローせよ。前述のプログラムの例外をハンド
ルせよ、またそれに対応する例外メッセージ "Unable to
calculte the logarithm for a negative value"を示せ。
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
public class example extends Applet implements ActionListener
{ private Label p1;
private TextField input;
private int x;
private double y[] = new double[10];
public void init()
{ p1=new Label("Enter a number (0 to 9)");
add(p1);input = new TextField(10);
input.addActionListener(this); add(input);
}
public void paint(Graphics g)
{ DecimalFormat precision2 = new DecimalFormat("#.00");
int xx= 70;
g.drawString("y[0~9]: ", 20, 50);
for(int i=0; i<y.length; i++)
{ g.drawString(precision2.format(y[i])+" ",xx,50); xx+=30;}
}
public void actionPerformed(ActionEvent e)
{ DecimalFormat precision2 = new DecimalFormat("#.00");
x = Integer.parseInt(input.getText());
y[x]= f(x);
showStatus("y["+x+"] = f("+x+")="+ precision2.format(y[x]));
input.setText(""); repaint();
}
public static double f(int x)
{ return 1.0/(double)(Math.log(2*x*x-5*x+2)); }
}
<html>
<applet code="example.class" width=450 height=100> </applet>
</html>
Exercise
1
Give the left applet program that calculates y = f(x) =
1/log(2x²-5x+2) for x=0~9, and puts the results into
an array y[10]. Type the program and the associative
HTML file, compile and run it. Input number 0 ~9 in
the text filed and watch what will be shown in the
applet. When you input a number less than 0 or
greater than 9, what exception messages are
displayed in your MS-DOS window? Handle this
ArrayIndexOutOfBoundsException using try/catch
blocks and show a message, “You must enter an
integer from 0 to 9”, when the exception occurs.
2
When you input a character(s) which is not an
integer, what exception messages are displayed in
your MS-DOS window? Handle this
NumberFormatException using try/catch blocks and
show a message, “You must enter an integer. Other
characters are illegal”, when the exception occurs.
3
When you input ‘1’, a special symbol will be shown.
This is because the variable of the log( ) function is a
negative value. Define an exception class
corresponding to this type of exception by referring
the DivideByZeroException class in the lecture note,
and throw the exception in the method f(int x) { … }.
Handle the exception in the previous program, and
show the corresponding exception message.
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
public class example extends Applet implements ActionListener
{ private Label p1;
private TextField input;
private int x;
private double y[] = new double[10];
public void init()
{ p1=new Label("Enter a number (0 to 9)");
add(p1);input = new TextField(10);
input.addActionListener(this); add(input);
}
public void paint(Graphics g)
{ DecimalFormat precision2 = new DecimalFormat("#.00");
int xx= 70;
g.drawString("y[0~9]: ", 20, 50);
for(int i=0; i<y.length; i++)
{ g.drawString(precision2.format(y[i])+" ",xx,50); xx+=30;}
}
public void actionPerformed(ActionEvent e)
{ DecimalFormat precision2 = new DecimalFormat("#.00");
x = Integer.parseInt(input.getText());
y[x]= f(x);
showStatus("y["+x+"] = f("+x+")="+ precision2.format(y[x]));
input.setText(""); repaint();
}
public static double f(int x)
{ return 1.0/(double)(Math.log(2*x*x-5*x+2)); }
}
<html>
<applet code="example.class" width=450 height=100> </applet>
</html>
課題
•
arrayIndexOutOfBoundExceptionを自分で定義して次のようなJav
aアプレットを作成せよ。自身で作成した
arrayIndexOutOfBoundExceptionの例外を備えさせ、TextFieldに
10個の整数を入力し、それを配列に格納するようなアプレット。
ex1
• devideByZeroExceptionを自身で定義し(レクチャーノートの
例を修正して分母を整数型でなくフロート型を扱えるように
する)、次のようなJavaアプレットを作成せよ。2つの
TextFieldにそれぞれフロート、もしくは整数型の数値を入力
し、割り算の計算をさせる。 ex2
課題
• Define your own arrayIndexOutOfBoundException.
Make a Java applet to input 10 integers from TextField, store
the integers in an array with considerations of handling
exception using your own defined
arrayIndexOutOfBoundException.
ex1
• Define your own divideByZeroException (modify the example
in today’s lecture note so that a denominator has a float type rather
than integer type ).
Make a Java applet that is able to input two numbers with
float or integer type from two TextField, and do calculation of
division (refer to the textbook fig. 12.1).
ex2