狠狠撸

狠狠撸Share a Scribd company logo
Javaプログラミング入門
第5回
今日の講義
? 例外
? インターフェース
闯补惫补プログラミング入门【第6回】
日常の『例外』とJavaの『例外』
? 普段の『例外』
? 「魚は空を飛ばない。けど、トビウオは例外」
? 規則に当てはまらないものを意味する

? Java言語の『例外』
? プログラムの誤りを検知し、適切なエラー処理を
行うための機構
? 普段の『例外』とは異なる
Java言語の例外
? 例外(exception)
1. 配列の長さを越えた添字で要素を参照した
?

ArrayIndexOutOfBoundsException

2. ファイルを開こうと思ったが、ファイルがな
かった
?

FileNotFoundException

3. メソッドに与えられた引数が異常な値だった
?

IllegalArgumentException

4. オブジェクトをたくさん作りすぎてメモリが足
りなくなった
? OutOfMemoryException
例外を起こしてみる
public class ExceptionTest1 {
public static void main(String[] args) {
int[] myarray = new int[3];
System.out.println("代入します");
myarray[100] = 0;
System.out.println("代入しました");
System.out.println("代入終了します");
}
}
例外が発生すると後続の処理は行わな
い
? 「代入しました」「終了します」は表示されな
かった
→プログラムが
myarray[100] = 0;
で例外(ArrayIndexOfBoundsException)が発生
したため、処理が中断されたため
? 例外が起きたことを「例外が投げられた」「例
外がthrowされた」と言う
例外をキャッチする
? 例外の処理を行うことを「例外を受ける」「例
外をcatchする」と言う
? 例外を正しくキャッチすることにより、後続の
処理を続行させることが出来る
例外をキャッチする例
public class ExceptionTest2 {
public static void main(String[] args) {
int[] myarray = new int[3];
try {
System.out.println("代入します");
myarray[100] = 0;
System.out.println("代入しました");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("代入できませんでした");
System.out.println("例外は" + e + "です");
}
System.out.println("終了します");
}
}
例外のイメージ
try {
例外のスロー

} catch (Exception e) {
例外のキャッチ

}
投げられてるのはクラスではなくイン
スタンス
? ArrayIndexOutOfBoundsException
? クラス名

? 「 ~Exception を投げる」と言うが、実際に投
げられているのはクラスではなくインスタンス
? catch (ArrayIndexOutOfBoundsException e)のe
はインスタンスを受け取る変数
階層化されたメソッド呼び出しから投
げられる例外
public class ExceptionTest3 {
public static void main(String[] args) {
int[] myarray = new int[3];
try {
System.out.println("代入します");
myAssign(myarray, 100, 0);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("代入出来ませんでした");
System.out.println("例外は" + e + "です");
}
System.out.println("終了します");
}
static void myAssign(int[] arr, int index, int value) {
System.out.println("myAssignに来ました");
arr[index] = value;
System.out.println("myAssignから帰ります");
}
}
実行してみる
コールスタック
? メソッド呼び出しの積み重ねのことをコールス
タック(call stack)と言う
? 「呼び出し(call)」「積み重なったもの(stack)」

? 例外が発生した場合、returnとは異なり、1つ前
のメソッドに戻るとは限らない。同じメソッド
内のcatch節に飛ぶかもしれないし、メソッドの
呼び出し元を遡って、初めて見つかったcatch節
にジャンプすることもある
? メソッド呼び出しと例外の仕組みを理解してい
ないと、プログラムの動きを見失うことになる
メソッドの処理を中断しても大丈夫な
のか?
? やりかけの仕事を途中で放棄してプログラムは
破綻しないのか?
? やりかけの仕事を放棄しても、try文を終了する前
に、finallyブロックで終了処理を書くことが出来
る
finallyブロックを使った例
public class ExceptionFinally {
public static void main(String[] args) {
System.out.println("Start");
try {
int[] a = new int[3];
System.out.println("代入します");
a[3] = 123;
System.out.println("代入しました");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("例外が発生しました " + e);
} finally {
System.out.println("finallyブロックです");
}
System.out.println("End");
}
}
代表的な例外処理の例
? 数への変換
? 文字列を整数値に変換する際に入力された文字が
数値でなかった場合
? NumberFormatException

? ファイル処理
? ファイルが存在しなかった場合
? FileNotFoundException

? ファイルを読んだりクローズする時にエラーが発
生した場合
? IOException
NumberFormatException
public class NumberTest {

+ e);

public static void main(String[] args) {
String numstr = "XYZ";
try {
int val = Integer.parseInt(numstr);
System.out.println("val = " + val);
} catch (NumberFormatException e) {
System.out.println("例外が発生しました "
}

}

}
自分で投げる例外
throws new IOException();
? 予約語throwsの後に投げたい例外のインスタン
スを記述することで、例外を投げることが出来
る
APIライブラリのマニュアル
public FileReader(String fileName)
throws FileNotFoundException
? FileNotFoundExceptionがthrows節によって表
現されている
例外の階層
Object

Throwable

Error

Exception

RuntimeException
それ以外の
Exception
例外の階層
? Throwable(throw + able):投げることが出来るク
ラス
? Errorは、もはや動作を継続するのは期待できな
い時に投げられるクラス
? Exceptionは、正しく例外処理を行って、動作が
継続することを期待するときに投げられるクラス
? RuntimeException:実行中に起こり、コンパイラに
よって前もってチェックされない例外
? その他のException:コンパイラによって前もって
チェックされる例外
チェックされる例外ですべきこと
? メソッドの中で
throw new IOException();
と記述していた場合
1. メソッド内のcatch節でその例外をキャッチす
ること
2. メソッドのthrow節でその例外を投げることを
宣言
? どちらか一方を必ずしなければならない
メソッド内のcatch節でその例外を
キャッチする
void someMethod() [
try {
...
throw new IOExcrption();
...
} catch (IOException e) {
...
}
}
メソッドのthrow節でその例外を投げ
ることを宣言
void someMethod() throws IOException {
...
throw new IOExcption();
...
}
「チェックされる例外」の意味
? 例外は「投げっぱなしには出来ない」
? 例外はキャッチするか、キャッチしない場合は
throwして上位のメソッドでキャッチして処理
を行わなければならない
「チェックされない例外」の意味
? 「いつどこで起こってもおかしくないような例
外」
? いつ、どこで起きるかわからないので、チェック
できない
例外の階層とcatch節
? 例外を正しくキャッチするには、例外自体の階
層を正しく理解する必要がある
? 投げられた例外をキャッチするのは、一番早く
マッチした例外
マッチする例外
try {

...
throw new IOException();
...
} catch (RuntimeException e) {
...
} catch (IOException e) {
// こちらが実行される
...
}
? IOExceptionはRuntimeExceptionの拡張クラスでは
ないため、RuntimeExceptionのcatch節には入らな
い
投げられた例外は親クラスを使って
キャッチ出来る
try {
...
throw new IOException();
...
} catch (Exception e) { // キャッチされる
...
}
? ExceptionクラスはIOExceptionクラスの親クラ
スなため、キャッチすることが出来る
例外を用いたプログラミングの注意点
? 例外を用いると、エラーが起きる場所とそのエ
ラーを処理する場所を分けることが出来る
? ただし、try文を注意深く作らなければ、例外が
どこで発生しているかわからなくなる
スタックトレース
? printStackTraceを使うと、どこで例外が発生し
たか見ることが出来る
printStackTraceを使った例
public class ExceptionTest4 {
public static void main(String[] args) {
int[] myarray = new int[3];
try {
System.out.println("代入します");
myAssign(myarray, 100, 0);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("代入出来ませんでした");
System.out.println("例外は" + e + "です");
e.printStackTrace();
}
System.out.println("終了します");
}
static void myAssign(int[] arr, int index, int value) {
System.out.println("myAssignに来ました");
arr[index] = value;
System.out.println("myAssignから帰ります");
}
}
finallyをうまく使う
? finallyブロックは例外が投げられても、投げら
れなくても、finallyブロックは必ず実行される
? finallyブロックの中には必ず行うべき後始末を
記述する
? ファイルのクローズ処理、ネットワークのコネク
ションクローズ処理など

? finallyブロックの中にはreturn文を記述してはい
けない
メソッドのエラー通知法
1. 戻り値でエラーを示す
?

jaav.io.InputStreamReaderクラスのread()メ
ソッドでは、ファイルの終端にたどり着き読み
込みが出来なくなった場合は、-1を返す

2. 例外でエラーを示す
?

java.io.DataInputStreamクラスのreadCharメ
ソッドではIOException、EOEExceptionを返す

3. 別の方法でエラーを示す
? java.io.PrintWriterクラスはcheckErrorメソッドを
呼び出して調べる必要がある
例外クラスの自作
? ゲームのプレイヤーが死んだ場合に、
DeadPlayerException
? Exceptionクラスの子クラスとして作る

? ハイスコアのファイルが読めない場合は、
HiScoreDataIOException
? IOExceptionの子クラスとして作る
演習1
? 次のようなプログラムを動かしていて、
method1~method3までのいずれかでException
が発生したとする。例外がどのクラスから投げ
られているかわかるように、mainメソッドを修
正しなさい
ExceptionTest5.java
public class ExceptionTest5 {
public static void main(String[] args) {
try {
mehod1(0);
mehod2(0);
mehod3(0);
} catch (Exception e) {
System.out.println("例外:" + e);
}
}
static void method1(int x) throws Exception{
}
static void method2(int x) throws Exception{
}
static void method3(int x) throws Exception{
}
}
演習2
? 10の会場を求めるつもりで次のプログラムを記
述したが、実行時にStackOverflowErrorという
例外が投げられた。どうしてか。また、このプ
ログラムをどう直せば10の階乗が求められる
か。なお、10の階乗とは
10×9 ×8 ×7 ×6 ×5 ×4 ×3 ×2 ×1
のことである
FactorialTest.java
public class FactorialTest {
public static void main(String[] args) {
System.out.println(factorial(10));
}
public static int factorial(int n) {
return n * factorial(n -1);
}
}
闯补惫补プログラミング入门【第6回】
インターフェースとは
? ここで学ぶインターフェースという単語は、
「人間とコンピュータのやりとりの約束事」
? インターフェースもクラスと同様参照型の一種
? インターフェースは、名前を持ち、フィール
ド、メソッド、スーパーインタフェース、サブ
インターフェースを持つ
クラスとインターフェースの違い
? インターフェースが持つフィールドは必ず定数
? インターフェースが持つメソッドは必ず抽象ク
ラス(メソッドは実装されない)
? インターフェースはインスタンスを作ることが
できない
インターフェースの定義
interface Lockable {
boolean lock();
boolean unlock();
}
? interface内で宣言されているメソッドはabstract
がついていなくても自動的に抽象クラスとなる
(メソッドの実装部分{}は記述できない)
? インターフェースの名前にはRunnableのように
-ableという言葉(接尾語)を付けることが多い
インターフェースの実装
public class Kinko implements Lockable {
@Override
public boolean lock() {
return false;
}
@Override
public boolean unlock() {
return false;
}
}
? 「実装」というのは「実際に装備する」という意味
extendsとimplementsの違い
? 「クラスの拡張」extends
? 「インターフェースの実装」implements
? Kinkoクラスはextends節がないため、スーパー
クラスはObjectクラスになる。KinkoでもObject
のメソッドを使うことが出来る(継承)
JewelBoxクラス(Boxクラスを拡張)を拡
張したLockableJewelBox
public class LockableJewlBox extends JewelBox implements
Lockable {
@Override
public boolean lock() {
return false;
}
@Override
public boolean unlock() {
return false;
}
}
クラス階層図
Lockableを実装
しているクラス

Object

Kinko

Box

JewelBox

LockableJewelBox
KinkoクラスとLockableJewelBoxクラス
の違い
? LockableJewelBoxは、JewelBox、Box、Object
のメソッドをすべて継承している
? LockableJewelBoxは、Lockableも実装している
ので、lock、unlockメソッドも持つ
? Kinkoクラスの親はObjectクラスのみ
? クラス階層の上ではあまり関係がない
? 無関係なクラスでもimplements Lockableを宣言
することによって、「共通のメソッド」をプログ
ラムで宣言することが出来る
例:DebugPrintableインターフェース
? プログラム実行中にインスタンスの内容をデ
バッグ出力する

public interface DebugPrintable {
void debugPrint();
}
DebugPrintableインターフェースを実
装したMyNumberクラス
public class MyNumber implements DebugPrintable {
int a;
public MyNumber(int a) {
this.a = a;
}
@Override
public void debugPrint() {
System.out.println("MyNumberのインスタン
ス:aの値は" + a + "です");
}
}
MyNumberクラスの動き
MyNumber num = new MyNumber(123);
とインスタンスを作ったとすると
num.debugPrint();
は
MyNumberのインスタンス:aの値は 123 です
と表示される
MyFileReaderクラス
? DebugPrintableインターフェースを実装し、FileReaderクラス(ファイル読み込みを行うク
ラス)を拡張する
public class MyFileReader extends FileReader implements DebugPrintable {
String filename = null;
public MyFileReader(String filename) throws FileNotFoundException {
super(filename);
this.filename = filename;
}
@Override
public void debugPrint() {
System.out.println("MyFileReaderのインスタンス:ファイル名は" +
filename + "です");
}
}
MyFileReaderクラスの動き
MyFileReader reader = new
MyFileReader("input.txt");
とインスタンスを作ったとすると
reader.debugPrint();
の実行によって
MyFileReaderのインスタンス:ファイル名は
input.txt です
と表示される
クラス階層図
Object
MyNumber

Reader
InputStreamReader

FileReader

MyFileReader
インターフェース型の変数
? インターフェースはインスタンスを作ることが
出来ない
DebugPrintable obj = new DebugPrintable(); ?
DebugPrintable obj = new MyNumber(123); ○
MyNumberはDebugPrintableインターフェースを
実装しているので、MyNumberのインスタンスは
DebugPrintable型の変数objに代入出来る
MyFileReaderの場合
DebugPrintable obj = new MyFileReader(123); ○
変数objはDebugPrintable型なので
obj.debugPrint();
は呼び出す事ができるが、
obj.read()
はコンパイルエラーになる(インターフェースで
定義されていないため)
((MyFileReader)obj).read();
とキャストすることで使用できるようになる
メソッドの引数でインターフェースを
利用する
public class MyInspector {
static void inspect(DebugPrintable obj) {
obj.debugPrint();
}
}
引数で与えられたobjがDebugPrintableインター
フェースを実装しているクラスであれば、そのイ
ンスタンスのdebugPrintメソッドを呼び出すこと
が出来る
インターフェースのフィールド
? インターフェースで宣言したフィールドは必ず
定数になる
? DebugPrintableインターフェースに次のような
フィールドを追加する
?
?
?
?

NO_ERROR
FILE_ERROR
MEMORY_ERROR
PREFIX
インターフェースのフィールド
public interface DebugPrintable {
int NO_ERROR = 0;
int FILE_ERROR = 1;
int MEMORY_ERROR = 2;
String PREFIX = "ERROR:";
void debugPrint();
}
インターフェースで宣言されているフィールドは、
自動的にpublic static final になる
スーパーインターフェース
? インターフェースはクラスと同様に拡張するこ
とが出来る

public interface FastRunnable extends Runnable {
void fastrun();
}
FastRunnableはRunnableのサブインターフェー
ス
多重継承とインターフェース
? クラスはスーパークラスを1つしか持つことが出
来ない
? MyMediaClass、MyReaderClass、
MyWriterClassという3つのクラスの性質を持つ
MyReaderWriterClassを作りたいと思っても、3
つのクラスからメソッドやフィールドを継承す
ることが出来ない
多重継承とインターフェース
? インターフェースを使うことにより、擬似的に
多重継承を実現することが出来る
? スーパークラスはMyMediaClassのみにし、あと
はインターフェースを使った「メソッド継承」
に統一する
? ただし、継承するのは名前のみで、実装は継承
しない
インターフェースは複数実装出来る
public interface MyReadable {
void read(byte[] data);
}
public interface MyWritable {
void write(byte[] data);
}
public class MyReaderWriterClass extends MyMediaClass implements MyReadable,
MyWritable {
@Override
public void write(byte[] data) {
}
@Override
public void read(byte[] data) {
}
}
クラスとインターフェースの比較
クラス

インターフェース

インスタンス

作れる

作れない

メソッド

いろいろ

必ずpublic abstract

フィールド

いろいろ

必ずpublic static final

スーパークラス

1つだけ

持てない

スーパーインターフェー
ス

複数指定可能
(implementsを使う)
class A implements B, c {
....
}

複数指定可能
(extendsを使う)
interface X extends Y,Z {
....
}
演習3
? クラスAlphaをスーパークラスに持ち、イン
ターフェースとBetaとGammaを実装したpublic
なクラスDeltaの宣言を記述しなさい。ただし、
クラスの内容は省略可
演習4
? 次のメソッドとフィールドを持つIconInfoとい
うpublicなインターフェースを定義しなさい
? 引数はint型で仮引数の名前はiconType、戻り値の
型はImage型で、名前がgetIconであるメソッド
? 型はintで名前はICON_16x16、値は1であるフィー
ルド
? 型はintで名前はICON_32x32、値は2である
フィールド
演習5
? 以下のMyMediaPlayableインターフェースを拡
張して、MySoundPlayableという名前のサブイ
ンターフェースを宣言しなさい。追加するメ
ソッドは以下のgetSoundNameである
? String getSoundName();
MyMediaPlayableインターフェース
interface MyMediaPlayable {
void play();
void stop();
void loop();
}
参考文献
? Java言語 プログラミングレッスン[第3版]下
? 结城浩摆着闭

More Related Content

闯补惫补プログラミング入门【第6回】