Back To Main

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ ◆Javaで珈琲ブレイク vol.018◆
┃……………………………………………………………………………………………
┃ [不定期] まぐまぐ ID=0000088576 Melma! ID=m00061296
┃……………………………………………………………………………………………
┃ 今回からご覧になる方は、バックナンバーご活用下さい
┃ http://javacafebreak.tripod.com
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

◆目次◆

■CPad for Javaアップデート ver 2.316
■BankAccountクラス verion 1.0821

皆さん、こんにちは。

Mr.Hackです。皆さんはいかがお過ごしですか?僕は長い夏休みも今週で終わり、来週からは、また、ハードな学期が始まります。秋のメインテーマは、オペレーティングシステムになりそうです。Cを使わないといけないので、毎日皆さんと同じように日々是決戦になりそうです。Red Hat Linux 7.3をいれてデュアルブートにしましたが、最近は簡単にディスプレイドライバも認識して、アっというまに、セットアップ完了です。暇を見つけては、Linuxをいじってみたいと思います。

■CPad for Javaアップデート ver 2.316
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ところで、久しぶりに、CPadをアップグレードしたのですが、これがまた、便利になってますねー。早速、Javaで珈琲ブレイクの読者の皆さんは、下記のサイトからダウンロードしてみましょう。

http://kklab.virtualave.net/cpad/

ダウンロードするバージョンは、2.316です。

どこが便利になったかといいますと、『javadoc作成機能』です。ダウンロードされた方は、早速試してみましょう。解凍したjcpad.exeを、以前インストールしたフォルダにコピーなり、移動なりして上書きしてあげればいいと思います。早速立ち上げて、今回のBankAccount.java(ver 1.0821)を開いてみましょう。もちろん、メルマガから、コピー&ペーストして、ファイル名はBankAccount.javaで保存してくださいね。

そして、メニューの『ツール』から、『ドキュメントの生成』か、『Packageのドキュメント生成』を選択すれば、javadocが生成され、htmlに関連ずけられているブラウザが自動的に立ち上がります。ちなみに、『ドキュメントの生成』を選択すると、現在選択しているウインドウ内のソースのドキュメントだけ、生成されます。『Packageのドキュメント生成』を選択すると、パッケージ内(同じフォルダ内)のソースコードのドキュメントがすべて生成されます。

どうです?ちょー、便利だと思いませんか?以前のように、右上のブルーの三角アイコンをクリックして、dos窓を開いて、javadocコマンド、クラス名を入れてというステップが、わずか、ワンクリックでできてしまいます。ここで、何か、コントロール・キーなどを用いて、ショートカットを用意してあれば、もーーーっと、べんりだなーと思います。ソースを書いていて、この/** */のコメントのところは、ちゃんと表示されるかな、と思ったときに、コントロール + 任意のキーでjavadocができるなら、それは、もう感動ものですね。

ただ、一つ残念なことがあるんです。それは、デフォルトでprivateなフィールド・メソッド等が表示されてしまっていることです。なぜ残念か皆さんわかりますか?javadoc作成は誰のためでしたっけ?自分のため?もちろんそうでしょう。しかし、本来の目的は、誰のためだと思います?そう、javadocを作成したクラスを利用するユーザーのためですね。ここで、ユーザーとは、あるクラスを使うプログラマです。ユーザーがprivateなフィールド等を使おうと思っても、privateなキーワードがついている故に使えないんです。これは、encapsulation(データの隠蔽)という概念と密接に関わってきますが、privateはフィールドは外のクライアントからは(クライアントとは、あるクラスを使う『クラス』をいう)アクセスできないのです。逆に言うと、アクセスする必要はないフィールドたちなのです。vol.000でニワトリの例を出しましたね。えさを与えたとき、ニワトリは太っていようと、やせていようと、卵さえ出してくれればいいと書きました。太っているために栄養が早く行き届いて2日で卵を産出しようと、栄養がないために、5日かかろうと、卵を産出してくれればいいのです。BankAccount.javaの例でいえば、hasLowerLetter()メソッドは、外部のBankAccountクラスを使うクライアントにとってはどうでもいいのです。むしろ、hasLowerLetter()メソッドが存在していようが、いまいが、知ったこっちゃないのです。hasLowerLetter()メソッド(privateメソッド)を使っているcheckPassword()メソッド(publicメソッド)さえ、ちゃんとpasswordが適切か否かを判断してくれさえすれば。ですので、通常は、javadocでもhasLowerLetter()メソッドは必要ありません。

体裁がちゃんと整っているかという、javadocチェックのためという観点からすれば、クラスにあるすべてのフィールド・メソッド・コンストラクタを表示するのは必要なことかもしれませんが、学習には、よろしくないかもしれませんね。データの隠蔽化という概念を促進するという意味でも。クリック一つでjavadocを生成できるのですから、デフォルトの(- private)をつけないメニューもあるともっといいですね。いいなと思いますが、いずれ対応してくれることを願いつつ、CPadを使っていきましょう。

『ツール』javadoc生成はとても便利な機能ですので、皆さんもバンバン使っちゃいましょう。javadocを作成する癖をつけて頂ければ、あなたは一端のプログラマです。誰と共同でプログラムを組んでも恥ずかしくありません。

それでは、BankAccountクラスの全てのコードです。CPadにコピー&ペーストしてBankAccount.javaで保存しておいてください。

■BankAccountクラス verion 1.0821
━━━━━━━━━━━━━━ ここから ━━━━━━━━━━━━━━━━━
/**
* バンク預金口座クラス。顧客の口座の出し入れ、残高
* 照会をおこなう(通貨単位:円)。預入引き落とし時、
* Precondition(事前条件)をチェックし、条件に合わない場合は、
* 例外を発生させる。accountId、passwordをセットするコンストラク
* タ(預金をゼロとする)、accountId、password、預金額をセット
* できるコンストラクタがある。また、一度に引き出せる上限は
* 2万円、一度に預金できる上限は10万円としてある。
*
* 例:
*
* <PRE>
* BankAccount account = new BankAccount("MrHack", "mRha9", 2000);
* try {
* account.deposit(1000);
* account.withdraw(500);
* }
* catch (Exception e) {
* Sytem.out.println("例外が発生しました:" + e.getMessage());
* }
* double currentBalance = account.getBalance();
* </PRE>
*
* アカウントIDが"MrHack"、パスワードが"mRha9"、2000円で口座を開設し、1000円を預金
* 後、600円を引き出して、現在の残高400円を<CODE>currentBalance</CODE>に保持する。
*
* @version 1.0821
* @since 1.0511
* @author Mr.Hack
* @see BankAccountTest テストクラス:BankAccountTest
*/
public class BankAccount {

/**
* 口座の残高
*/
private double balance;
/**
* 一度に預け入れる上限額
*/
private final double MAX_DEPOSIT_AMOUNT = 100000.0;
/**
* 一度に引き落とせる上限額
*/
private final double MAX_WITHDRAW_AMOUNT = 20000.0;
/**
* アカウントID
*
* @since 1.0731
*/
private String accountId;
/**
* パスワード
*
* @since 1.0731
*/
private String password;

/**
* アカウントIDとパスワード、残高をセットするコンストラクタ。初期化時(新しい口座作成時)、
* <code>amount</code>は残高としてセットする。
*
* @since 1.0731
* @param accountId アカウントID
* @param password パスワード
* @param amount 口座に預け入れる金額(預金)
* @exception IllegalArgumentException
* <code>accountId</code>が不適切な文字列の場合、
* <code>password</code>が不適切な文字列の場合、
* <code>amount</code>がゼロかマイナスの場合、
* 定められた一度に預金できる金額を上回った場合、例外発生。
*/
public BankAccount(String accountId, String password, double amount) {
setAccountId(accountId); //不適切な文字列の時IllegalArgumentExceptoinをスロー
setPassword(password); //不適切な文字列の時IllegalArgumentExceptoinをスロー
if (amount < 0) {
throw new IllegalArgumentException("入力した金額はマイナスです。");
}
if (amount > MAX_DEPOSIT_AMOUNT) {
throw new IllegalArgumentException("一度に入金できる額の上限は" + MAX_DEPOSIT_AMOUNT + "です。");
}
this.balance = amount;
}


/**
* アカウントIDとパスワをセットするコンストラクタ
*
* @since 1.0731
* @param accountId アカウントID
* @param password パスワード
* @param amount 口座に預け入れる金額(預金)
* @exception IllegalArgumentException
* <code>accountId</code>が不適切な文字列の場合、
* <code>password</code>が不適切な文字列の場合、例外発生。
*/
public BankAccount(String accountId, String password) {
this(accountId, password, 0);
}

/**
* 残高をゼロにセットするデフォルトコンストラクタ。初期化時、
* 残高をゼロにセットする。
*
* @deprecated accountIdとpassword設置により、version 1.0731から{@link #BankAccount}を推奨。
* @see #BankAccount
*/
public BankAccount() {
this.balance = 0;
}

/**
* <code>amount</code>分を残高としてセットするコンストラクタ。初期化時(新しい口座作成時)、
* 預金額を残高としてセットする。
*
* @deprecated accountIdとpassword設置により、version 1.0731から{@link #BankAccount}を推奨。
* @see #BankAccount
* @param amount 口座に預け入れる金額(預金)
* @exception IllegalArgumentException <code>amount</code>がゼロかマイナスの場合、
* 定められた一度に預金できる金額を上回った場合
*/
public BankAccount(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("入力した金額はマイナスです。");
}
if (amount > MAX_DEPOSIT_AMOUNT) {
throw new IllegalArgumentException("一度に入金できる額の上限は" + MAX_DEPOSIT_AMOUNT + "です。");
}
this.balance = amount;
}

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

/**
* <code>amount</code>分の金額を引き出す。<code>amount</code>がゼロかマイナスの時、
* 引き落とし金額が残高を上回った時、
* あるいは、一度に引き出せる上限金額を上回った時、例外発生。
*
* @param amount 引き出す金額
* @exception IllegalArgumentException <code>amount</code>がゼロかマイナスの場合、
* 引き出し額が残高を上回った場合、
* または、一度に引き出せる金額を上回った場合
*/
public void withdraw(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("入力した金額は0かマイナスです。");
}
if (balance < amount) {
throw new IllegalArgumentException("残高を超えています。");
}
if (amount > MAX_WITHDRAW_AMOUNT) {
throw new IllegalArgumentException("一度に引き落としできる額の上限は" +
MAX_WITHDRAW_AMOUNT + "です。");
}
this.balance -= amount;
}

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


/**
* 現在の残高を戻り値として返す。
*
* @deprecated メソッド名が不適切なため、Version 1.0518から{@link #getBalance}に入れ替わり。
* @see #getBalance
* @return balance 口座にある現在の残高
*/
public double getBlance() {
return this.balance;
}

/**
* アカウントIDをセットする。アカウントIDが適切ではない場合は例外が発生する。
* 例外が発生する事前条件は{@link #checkAccountId}参照。
*
* @since 1.0731
* @see #checkAccountId
* @param accountId アカウントIDの文字列
* @exception IllegalArguementException アカウントIDの事前条件を満たしていない場合
*/
public void setAccountId(String accountId) {
if (!BankAccount.checkAccountId(accountId)) {
throw new IllegalArgumentException("アカウントIDが正しくありません。");
}
this.accountId = accountId;
}


/**
* アカウントIDを得る。
*
* @since 1.0731
* @return accountId アカウントIDの文字列
*/
public String getAccountId() {
return this.accountId;
}

/**
* パスワードをセットする。パスワードが適切ではない場合は例外が発生する。
* 例外が発生する事前条件は{@link #checkPassword}参照。
*
* @since 1.0731
* @see #checkPassword
* @param password パスワードの文字列
* @exception IllegalArguementException パスワードの事前条件を満たしていない場合
*/
public void setPassword(String password) {
if (!BankAccount.checkPassword(password)) {
throw new IllegalArgumentException("パスワードが正しくありません。");
}
this.password = password;
}

/**
* 文字列accountIdが適切な値かどうかをチェックする。
* <PRE>
* 1.nullでもなく、3文字未満ではない
* 2.小文字、または、大文字である
*
* 上記の条件を満たした場合に、<code>true</code>を返す
* </PRE>
*
* @since 1.0731
* @param accountId アカウントIDの文字列
* @return <code>true</code> 事前条件を満たした場合
* <code>false</code> それ以外の場合
*/
public static boolean checkAccountId(String accountId) {
/**
* accountIdがnullか、3文字未満の場合
*/
if (accountId == null || accountId.length() < 3) {
return false;
}
char character;
/**
* 小文字ではなく、かつ、大文字ではない場合
* = NOT 'a' <= character <= 'z', AND NOT 'A' <= character <= 'Z'
* = 'a' > character, OR character > 'z', AND
* 'A' > character, OR character > 'z'
*/
for (int i = 0; i < accountId.length(); i++) {
character = accountId.charAt(i);
if ((character < 'a' || character > 'z') &&
(character < 'A' || character > 'Z')) {
return false;
}
}
/**
* 事前条件を全て満たした場合、return true
*/
return true;
}


/**
* 文字列passwordが適切な値かどうかをチェックする。
* <PRE>
* 1.nullでもなく、5文字未満ではない
* 2.大文字、小文字、または、数字である
* 3.大文字、小文字、数字それぞれ少なくとも一字ずつ含む
*
* 上記の条件を満たした場合に、<code>true</code>を返す
* </PRE>
*
* @since 1.0731
* @param password パスワードの文字列
* @return <code>true</code> 事前条件を満たした場合
* <code>false</code> それ以外の場合
*/
public static boolean checkPassword(String password) {
/**
* passwordがnullか、5文字未満の場合
*/
if (password == null || password.length() < 5) {
return false;
}
/**
* 小文字ではなく、大文字でもなく、かつ、数字でもない場合
*/
char character;
for (int i = 0; i < password.length(); i++) {
character = password.charAt(i);
if ((character < 'a' || character > 'z') &&
(character < 'A' || character > 'Z') &&
(character < '0' || character > '9')) {
return false;
}
}
/**
* 大文字を含まないか、小文字を含まないか、数字を含まないかのいずれかの場合
*/
if (!hasUpperLetter(password) || !hasLowerLetter(password) || !hasNumber(password)) {
return false;
}
/**
* 上記の条件を全てクリアーした場合
*/
return true;
}


/**
* アルファベットの大文字が少なくとも一文字含まれているかチェックする。
*
* @since 1.0731
* @param stringValue チェックする文字列
* @return <code>true</code> 大文字が一文字でも含まれていた場合
* <code>false</code> それ以外の場合
*/
private static boolean hasUpperLetter(String stringValue) {
if (stringValue == null || stringValue.length() == 0) {
return false;
}
char character;
for (int i = 0; i < stringValue.length(); i++) {
character = stringValue.charAt(i);
if (character >= 'A' && character <= 'Z') {
return true;
}
}
return false;
}


/**
* アルファベットの小文字が少なくとも一文字含まれているかチェックする。
*
* @since 1.0731
* @param stringValue チェックする文字列
* @return <code>true</code> 小文字が一文字でも含まれていた場合
* <code>false</code> それ以外の場合
*/
private static boolean hasLowerLetter(String stringValue) {
if (stringValue == null || stringValue.length() == 0) {
return false;
}
char character;
for (int i = 0; i < stringValue.length(); i++) {
character = stringValue.charAt(i);
if (character >= 'a' && character <= 'z') {
return true;
}
}
return false;
}


/**
* 数字が少なくとも一文字含まれているかチェックする。
*
* @since 1.0731
* @param stringValue チェックする文字列
* @return <code>true</code> 数字が一文字でも含まれていた場合
* <code>false</code> それ以外の場合
*/
private static boolean hasNumber(String stringValue) {
if (stringValue == null || stringValue.length() == 0) {
return false;
}
char character;
for (int i = 0; i < stringValue.length(); i++) {
character = stringValue.charAt(i);
if (character >= '0' && character <= '9') {
return true;
}
}
return false;
}

/**
* ユーザーがログイン時入力したパスワード(<ccde>password</code>)と
* 口座のパスワード(<code>userPassword</code>)を比較して一致
* しているかどうかを確かめる。
*
* @since 1.0731
* @param userPassword ユーザーがログイン時に入力したパスワード
* @return <code>true</code> 口座のパスワードと一致した場合
* <code>false</code> それ以外の場合
*/
public boolean equalsToPassword(String userPassword) {
return this.password.equals(userPassword);
}
}
━━━━━━━━━━━━━━ ここまで ━━━━━━━━━━━━━━━━━

次回は、BankAccount#checkAccountId()にでてきた、staticキーワードを取り上げてみます。staticキーワードがついているメソッドと、ついていないメソッドはどこが違うのでしょうか?

それでは、皆さん、また会いましょう。

Mr.Hack

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

© 2002 MR.HACK ALL RIGHTS RESERVED