Back To Main

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ ◆Javaで珈琲ブレイク vol.006 後編◆
┃……………………………………………………………………………………………
┃ [不定期] まぐまぐ ID=0000088576 Melma! ID=m00061296
┃……………………………………………………………………………………………
┃ 今回からご覧になる方は、バックナンバーもご活用下さい
┃ http://www.melma.com/mag/96/m00061296/
┃ http://backno.mag2.com/reader/Back?id=0000088576
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

◆目次◆

■throwキーワードとthrowsキーワード
■Question 6


前編の続きです。

■throwキーワードとthrowsキーワード
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

例外を発生させたい場合は、throwキーワードを使うことでいつでも例外を発生させることができます。例えば、Exceptionクラスの例外を発生させたいときは、

throw new Exception();

または、例外のメッセージをつけて、

throw new Exception("例外が発生しました");

とします。そして、throwキーワードで例外が発生すると、throwを含むメソッドはそれ以降の文を実行せずにプログラムの流れをメソッドを使ったところ(呼ばれたところ)まで戻します、これだけでは、いまいち、ピンときませんね。実際に使ってみましょう。まずは、預金する金額がマイナスやゼロ(ゼロ円を預金するということは、預金口座では意味をなさない)であるときは、例外を発生させて、

balance += amount;

を実行しないようにします。

void deposit(double amount) throws Exception {
if (amount <= 0) {
throw new Exception("入力した金額は0かマイナスです。");
}
balance += amount;
}

if文でamountの値をチェックし、amountがゼロかマイナスの時は、throwキーワードをつかって例外を発生させます。このように、balance += amountを実行する前にif文でパラメーター等をチェックすることをPrecondition(前提条件)といいます。値がパラメータとして渡されたときにif文でチェックして値が不正なら例外をthrowしてそれ以降を実行させません。

ここで、もうひとつ新しいキーワードが出てきました。メソッドを定義している行に、throwsキーワードあります。これは、sがついていて、throwキーワードとは違います。こちらのthrowsキーワードはメソッド定義の時に使われます。メソッド(三人称単数)がスローするので、throws(s付き)です。メソッドの中のthrowは、あなた(プログラマ)がメソッドにスローしなさい(命令形)とするので、throw(sなし)と覚えるとこんがらがらないでしょう。throwsの意味は、deposit()メソッドはExceptionという例外を投げますよ、という意味です。だから、このdeposit()メソッドを使う側では、try&catch構文を使ってキャッチするか、

BankAccount account = new BankAccount();
try {
account.deposit(-1);
}
catch (Exception e) {
do something
}

他のメソッド(例えば、otherMethod()メソッド)の中でdeposit()メソッドを使う場合はそのメソッド(otherMethod()メソッド)がスロー宣言しないといけません。

void otherMethod(double amount) throws Exception {
BankAccount account = new BankAccount();
account.deposit(amount);
}

もし、throwsキーワードを使ってスロー宣言をしないと、

例外 java.lang.Exception は報告されません。スローするにはキャッチまたは、スロー宣言をしなければなりません。

となり、コンパイルエラーになります。また、Exceptionクラスのオブジェクトをthrowで投げたときに、throwsキーワードでExceptionのサブクラス(例えば、IOException)を宣言してもコンパイルエラーになります。

// スロー宣言がIOExeption(Exceptionのサブクラス)のため、
//コンパイルエラー
void deposit(double amount) throws IOException {
if (amount <= 0) {
throw new Exception("入力した金額は0かマイナスです。");
}
balance += amount;
}

さて、上記の方法を使って、deposit()メソッドを仕上げましょう。Preconditionで一度に入金できる金額を制限してみましょう。実際には、高額の金額を入金しても問題はないかもしれませんが、アメリカのある銀行では、200ドル以上の金額を入金するとすぐにはdepositとなりません。後日、銀行員が金額をチェックしてから残りdepsitなります。というのも、現金を預金するときも封筒にれて、ATMに預けるためです。Mr.Hackは日本のように、現金を預けたときATMが実際の金額をチェックして、その場で全額入金されるといいな、と常日頃思うのですが、アメリカの銀行のおもしろいところです。封筒をつかう意味は、たぶん、チェック(小切手)も封筒に入れるシステムなので、チェックが実際いくら入金されたかを銀行員がチェックしないといけないためなのではないかな、と思います。ここでは、練習のため、2万円以上一度に入金することを禁止してみましょう。以下が、完成したdeposit()メソッドのBankAccount.javaクラスです。

【BankAccount.java】
━━━━━━━━━━━━ ここから ━━━━━━━━━━━━━━━━━━
/**
* バンク預金口座クラス。顧客の口座の出し入れ、残高
* 照会をおこなう(通貨単位:円)。預入時、
* Precondition(条件)をチェックし、条件に合わない場合は、
* 例外を発生させる。残高をゼロとするデフォルトのコンストラクタ、
* 預金額をセットできるコンストラクタがある。
* @author Mr.Hack
*/
public class BankAccount {

/**
* 口座の残高
*/
private double balance;
/**
* デフォルトコンストラクタ。初期化時、
* 残高をゼロにセットする。
*/
public BankAccount() {
this(0);
}

/**
* 預金額付きコンストラクタ。初期化時(新しい口座作成時)、
* 預金額を残高としてセットする。
*
* @param amount 口座に預け入れる金額(預金)
*/
public BankAccount(double amount) {
this.balance = amount;
}

/**
* amount分を預金として口座に預ける。amountがゼロかマイナスの時、一度に預ける
* 上限金額を上回った時、例外を発生させる。
*
* @param amount 口座に預け入れる金額(預金)
* @exception Exception amountがゼロかマイナスの場合、定められた一度に預金できる
* 金額を上回った場合、例外発生。
*/
public void deposit(double amount) throws Exception {
if (amount <= 0) {
throw new Exception("入力した金額は0かマイナスです。amount: " + amount);
}
if (amount > 20000) {
throw new Exception("一度に入金できる額の上限は20000円です");
}
this.balance += amount;
}

/**
* amount分の金額を引き出す
*
* @param amount 引き出す金額
*/
public void withdraw(double amount) {
this.balance -= amount;
}

/**
* 現在の残高を戻り値として返す。
*
* @return balance 口座にある現在の残高
*/
public double getBlance() {
return this.balance;
}
}
━━━━━━━━━━━━ ここまで ━━━━━━━━━━━━━━━━━━

今週の宿題にいっていましょう。

■Question 6
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1.BankAccountTest.javaをコンパイル・実行したときに全てのテストが成功するように、BankAccount.javaを完成させなさい。

2.BankAcount.javaのメソッドgetBlance()は、getBalance()の間違いである。既存のテストが失敗しないよう(Question5の解答のテストコードは変えてはならない)getBalance()用のテストケースを付け加えなさい。また、getBalance()メソッドのテストもgetBlance()メソッドと同じように、BankAccountTestクラスに付け加えなさい。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ヒント

前回、上司にテストクラスを作成せよ、と命じられ、BankAccountTestクラスのテストするコードを書きました。上司は、新米のあなたの出来に非常に満足です。あなたは、作成中にgetBlanceのBlanceを辞書で調べますが、でていません。これは、Balanceの間違いではないかと思い、上司に相談すると、どうやらgetBalance()の間違いのようです。しかしながら、すでに、API仕様とともに、インターネット上に公開されてしまったようです。さて、困りました。すでにBankAccount.classをAPIとして使用しているユーザーもいるかもしれません。getBlanceメソッドを消し、getBalanceメソッドを付け加えるのは簡単です。Bとlの間にaを入れればいいのです。しかし、それによって、getBlanceを使っているユーザーはアップデートによって、getBlance()が使えなくなり、多大な損害を被ってしまいます。そこで上司は"Deprecated"(推奨されていない)とすることで、getBlanceメソッドを残すことに決めました。Java documentationにはgetBalance()メソッドを使うことを推奨する旨を記述することにしました・・・。

deposit()メソッドは完成させたので、残すは、withdraw()メソッドです。
APIをみて3つの場合を考えてみてください。

1.ゼロ・マイナスの場合
2.残高を上回った場合
3.10万円という上限を上回った場合

今回は、getBlance()のテストで、getBlanceが”シンボルを解釈処理できません。”とならないように、BankAccountでgetBlanceを残します。そのまま、getBalance()メソッドのテストもしてください。

さて、今回のテストの概念は、はじめてふれられた方もいるかもしれません。今回の号で分からないところや、わかりづらいところがあれば、下記の掲示板から質問をいただければ幸いです。また、初心者の方の基本的な質問も大歓迎です。

それでは、またあいましょう。hava a nice day.

Mr.Hack


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆Javaで珈琲ブレイク◆
────────────────────────────────────
皆様からの激励・批判のメールをお待ちしております。
【発行者】 Mr.Hack - javacafebreak@hotmail.com
【掲示板】 http://fweb.midi.co.jp/~romanhikou/cafe_entrance.html
※質問は上記の掲示板からどうぞ。
【サイト】 http://mrhack.hoops.ne.jp/
【発行数】 まぐまぐ[810] Melma[108]
【解除】http://mrhack.hoops.ne.jp/
※解除は上記のサイトからいつでもできます。
────────────────────────────────────
(c)2002 MR.HACK ALL RIGHTS RESERVED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

© 2002 MR.HACK ALL RIGHTS RESERVED