例外処理の蝶きほん

例外処理をしたいケースは2つ。

  1. 通常だとプログラムが停止するエラーでも停止しないようにする処理
  2. 「負の数はエラーにする」といった独自に設定したいエラーの処理

通常だとプログラムが停止するエラーを停止しないようにする処理

→try-catchを使う

  1. エラーが発生する可能性のあるぶぶんをtryでかこむ
  2. 発生を想定しているエラーが起きた時の処理(ハンドラ)をcatchにかく

例:キーボード入力のStringをintにキャストする

String str = br.readLine();
try {
	int no = Integer.parseInt(str);
} catch (NumberFormatException e) {
	System.out.println("数字をいれてよ");
}	

「負の数はエラーにする」といった独自に設定したいエラーの処理

  • 想定するエラーに対応したExceptionのサブクラスを作成
  • 作成したエラークラスからインスタンスを生成する
  • エラーにしたい条件が発生したら、エラーインスタンスを送出(スロー)する
  • スロー文をtryで囲む
  • 作成したクラスをキャッチするcacth文を追加する

例:負の数はエラーにする

int num = Integer.parseInt(br.readLine());
if(num < 0){
	try{
		throw new NoNullException();
	} catch(NoNullException e){
		System.out.println("数字をいれてよ");
	}
} else {
	//正の数におこなう処理
}

キャッチ☆ザ☆例外 〜例外のスローとExceptionのサブクラス

(しばらくJava勉強メモになります)
Word君の例外処理について

まとめ

投げた例外はかならずキャッチしよー!

問題

「作成したWord君には例外処理対策がされていません。メニューの該当番号以外を入力した場合や番号以外を入力した場合の例外処理を記述してください。本例外を示すクラスとして、NoNullExceptionクラスを作成すること」

考察

  • A:数字以外:Integer.parseInt(str)でNumberFormatExceptionが発生
  • B:メニューの該当番号:1,2,3以外はエラー扱いにする

処理内容

A:数字以外:Integer.parseInt(str)でNumberFormatExceptionが発生
→「入力されたstrをint型にキャストして、proc()にわたす」部分をtry-catch処理

User.java

// 入力された数字を引数としてワード君へ
String str = br.readLine();
try {
	int no = Integer.parseInt(str);
	boo = wk.proc(no);
} catch (NumberFormatException e) {
	System.out.println("ちゃんと番号えらんでよ。");
}

B:メニューの該当番号:1,2,3以外はエラー扱いにする
→1-3でなかったらNoNullExceptionクラスの例外をスロー&キャッチする処理を、proc()内switchでメニュー処理を振り分ける前に追加

ミニマムに書くと…

WordKun.java
public boolean proc(int no) throws NoNullException, IOException{
boolean boo = true;

	// 1-3でなかった場合
	if(no < 1 | 3 < no){
		try{
			throw new NoNullException();			
		}catch (NoNullException e) {
			System.out.println("ちゃんと番号えらんでよ。");
		}
	} else {
	// 1-3 の場合各処理
		switch(no){
		case 1:
		(以下略)
		break;
		}
	}
}

もちろんおなじtry-catchにまとめる

User.java

// 入力された数字を引数としてワード君へ
String str = br.readLine();
try {
	int no = Integer.parseInt(str);
	boo = wk.proc(no);
} catch (NumberFormatException e) {
	System.out.println("ちゃんと番号えらんでよ。");
} catch (NoNullException e) {
	System.out.println("ちゃんと番号えらんでよ。");
}

さらにException1つまでまとめてキャッチしてもよいかも。

// 入力された数字を引数としてワード君へ
String str = br.readLine();
try {
	int no = Integer.parseInt(str);
	boo = wk.proc(no);
} catch (Exception e) {
	System.out.println("ちゃんと番号えらんでよ。");
}

わしがはまったところ

Exceptionのサブクラスとして作成したNoNullExceptionをスローする処理を考える。

  • A: catch(NoNullException, e)でキャッチ:OK
  • B: catch(Exception, e)でキャッチ:OK,スーパークラスでもキャッチ可能
  • C:Exceptionってデフォルト処理でしょ?書かなくてもキャッチされるのではないのか?

→例外ハンドラを記述しないでデフォルト処理にまわると、「finally処理実行→デフォルトエラー処理→終了」になって止まってしまう

まとめ

投げた例外はかならずキャッチしよー!

参考:Javaの道

http://www.javaroad.jp/java_exception2.htm
まんなかにある「例外の処理フロー」図がわかりやすいです。

privateなコンストラクタの使い道

コンストラクタにもprivateがつけられますという話がありましたが
コンストラクタってインスタンス生成時に自動的に呼び出されるんでしょ?
privateつけたらインスタンスつくれないじゃん?

  • staticフィールド・メソッドのみのクラスを作成した際にインスタンスの生成を禁止する

http://blogs.yahoo.co.jp/sister_ray999/16812136.html

 →コンストラクタにはprivateをつけて、メソッドからインスタンス生成する
http://www.sk-jp.com/java/pattern/singleton.html

…といった場合に使うワザのようです。

りんごパッケージとサブパッケージの関係は「赤の他人」

eclipse上で、パッケージ「pkg」があるときに、サブパッケージ「pkg.sub」を作成します。
すると(Windowsの)エクスプローラではフォルダpkgの中にフォルダsubが作成されています。
…が!Javaプログラム上はsubがpkgのサブパッケージであるというような親子関係は認識しません。

つまり…

  • ファイル構造はpkg/subになる
  • プログラム記述上はpkg.subとなる

一方で

  • 「pkg」と「pkg.sub」の間には、superで親を指すとか、

変数のスコープが子にもおよぶといったプログラム上の「親子関係」はまったく存在しない。
「pkg」と「pkg.sub」の関係は、「pkg」と(無関係な別パッケージ)「pkg2」の関係と同じ。

eclipseのパッケージエクスプローラで、サブパッケージがいわゆるサブフォルダのように表示されないのはそんな理由でした。