Back To Main

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

皆様、ご無沙汰しております。
Mr.Hackです。いろいろな方から、もう、発行しないのか、等の励ましのメールをいただきありがとうございました。

9月以降、秋学期が始まり、とても忙しい日々を送ってきました。今学期は、先学期以上に実りの学期になりそうです。Javaに関していえば、strutsフレームワークによる、Web Applicationの開発、Eclipse IDEとの出会い、C#によるWeb Applicationの開発、そして、暗号・電子署名の知識等、とても楽しく、あっという間に11月ももう終わりです。また、Java言語についても少しずつ、新しいトピックを吸収しております。

この吸収した知識を生かすべく、12月中旬には、Javaで珈琲ブレイクを再開したいと思っております。今までのメルマガのスタイルで行こうとは思っていますが、こんなトピックを扱ってほしい等ありましたら、メール頂けると幸いです。皆様のご要望にできるだけ添いつつ、新しい知識を紹介していきたいと思っております。
IDEに関してですが、JBuilerの解説を待ち望んでいた方には、大変申し訳ございません。方針を若干変更し、JBuilderはWeb等で扱うようにしようとおもっています。『なんだよ、結局JBuilder7扱わないのかよ、しかも、もうJBuilder8がでちゃうぜ』と思っている方もいらっしゃるかもしれません。しかしながら、JBuilder8は、新しい仕様を見る限り、Personal Editionに限っては、何ら、新しくなっておりません。いまだ、JUnitもサポートしないし、Antもサポートしません。ということは、JBuilder8は、Javaで珈琲ブレイクでの利用に限っていえば、全くふさわしくないプロダクトだといわざるを得ません。Mr.Hackも9月までは、JBuilderユーザーだったので、どうやって使うの?等、回答できるところがあると思います。メールなりで問い合わせて頂ければ、回答させて頂きたいと思います。

それでは、何を使うの?

という方には、『Eclipse』です。http://eclipse.orgからどんなものかアクセスできます。スクリーンショットをご覧になりたい方は、こちらからご覧ください。http://www2.hawaii.edu/~takuyay/eclipse/welcome.html

これは、すごいですよ。なんていいましても、オープンソース。IBMが$40million(50億円近く?)に値する技術提供をしたというだけのことはある製品です。ソフトウェアエンジニアリングで、ある意味デファクトスタンダードとなっている、JUnit、Ant、CVS、Refactoring、Javadoc作成等標準でサポートしています。しかもフリー。

もし、あなたが、日曜プログラマで、ノートパットで、コマンドプロンプトから、実行して、それで十分満足ハッピー、世界の動向なんてどうだっていいのよん。という方は、気にしないでください。今までのお話をお忘れください。

いずれ、日本でも、もっと、ソフトウェアエンジニアリングが脚光を浴びれば、Eclipseのハウツー本なる本も出てくるのではないかなと思います。4ヶ月ほどで新しい製品がでるJBuilder Enterpriseに36万円も投資できる個人の方がいらっしゃいますか?値段云々は抜きにしても、オープンソースなJUnitやAntをEnterprise Versionじゃないと(JBuilderと)使えない、というのも、どうかと思う限りです。

そんなこんなを、この9月からの約3ヶ月の間考え、Eclipseでいけると思うようになりましたので、12月からは、ちょくちょく、Eclipseでプログラミングをしていこうと思います。日本でも、草の根といったらへんですが、企業単位ではなく、学術レベルや、個人レベルでも、高度なソフトウェアエンジニアリングの知識を吸収して行かなくてはならない時期にきていると思います。お金を持っている企業しか・・・というレベルでは、いつまでたっても、日本はソフトウェア立国には慣れない気がしてなりません。

というわけで、来月から、また、Javaで珈琲ブレイクを再開したいと思っております。どうぞよろしくお願いします。

以下は、先日、熱心な読者の方からいただいた、メールに対する回答です。興味のある方は、ご覧ください。

> 掲示板初投稿です。「Javaで珈琲ブレイク」大変お世話になっております。今
> 回はvol.018 BankAccountクラスを解読中に?と思っ たことがありました。今
> まで疑問に思わなかったのですが、コンストラクタなるものがさっぱりわから
> なくなってしまいましたので質問させ ていただきます。
>
> public BankAccount(String accountId, String password, double amount) {
> setAccountId(accountId); //不適切な文字列の時IllegalArgumentExceptoinをスロー
> setPassword(password); //不適切な文字列の時IllegalArgumentExceptoinをスロー
>
> こちらのコンストラクタはsetAccount()とsetPassword()を使用してaccountId
> やpasswordのチェックをしてからセットしていますよね。 でもそのあとのコ
> ンストラクタはなぜ this(accountId, password, 0);としてaccountIdやpassword
> のチェックをしていないのでしょう か?多分私のコンストラクタの考え方が
> ズレているのでしょう。コンストラクタとははどのようなものなのでしょうか
> ?

コンストラクタは、クラス名と同じ名前で、戻り値がない、特別なメソッドと、覚えておくといいかもしれません。例えば、クラス名がFooとすると、コンストラクタは、Foo()となります。

class Foo {
// コンストラクタ
Foo() {}
}

コンストラクタは、必ずクラスに一つ存在します。しかしながら、省略することも可能です。省略した時は、Foo() { super();}が呼ばれていることを意味します。例えば、

class Foo {
}

は、

class Foo {
Foo() {
super();
}
}

と同じ意味になります。

では、コンストラクタは、省略もできるし、いったい役割は何なの?とお思いでしょう。

コンストラクタの主な役割は、新しいインスタンス生成時に、必要な初期化を一緒にすること、です。言い換えれば、インスタンス生成時に、初期化忘れを防ぐこと、です。簡単な例を挙げますと、

class BankAccount {
private double balance;
private String accountHolderName;
}

これは、文法的に正しいです。インスタンスフィールドがprivateですから、このクラスのクライアント(例えば、BankUserInterfaceクラス)は、アクセスできませんので、settter、getterメソッドが必要になりますね。
/**
* バンクアカウントサンプルクラス
* @version 1.1127
* @author Mr.Hack
*/
class BankAccount {
/** 預金残高 */
private double balance;
/** 預金者氏名 */
private String accountHolderName;
/**
* 預金残高をセットする
* @param balance 預金残高
*/
public void setBalance(double balance) {
this.balance = balance;
}
/**
* 預金残高を得る
* @return 預金残高
*/
public double getBalance() {
return this.balance;
}
/**
* 預金者氏名をセットする
* @param accountHolderName 預金者氏名
*/
public void setAccountHolderName(String accountHolderName) {
this.accountHolderName = accountHolderName;
}
/**
* 預金者氏名を得る
* @return 預金者氏名
*/
public String getAccountHolderName() {
return this.accountHolderName;
}
}

クライアントであるBankUserInterfaceクラスは、例えば、以下のように使うでしょう。

BankAccount account = new BankAccount();
account.setBalance(2000.00);
account.setAccountBankHolderName("Mr.Hack");
...

しかしながら、もし、"Mr.Hack"の文字列をsetterメソッドを使ってセットせずに、getterメソッドで文字列を得ようとしたらどうなるでしょう。

BankAccount account = new BankAccount();
/**
* BankAccount内部のthis.accountHolderNameは
* インスタンス生成時、nullで初期化されるので、
* nullを指している。そのため、account.getAccountHolderName()は
* nullの参照を戻り値として返す。
*/
String myName = account.getAccountHolderName();

この場合は、BankAccountクラス内のthis.accountHolderNameの参照変数がnullを指したままなので(Stringのような参照型は、デフォルトで、nullで初期化される)、もし、名前を比較するために、.equals()メソッドをmyNameに適用しようとすると、

myName.equals("Mr.Hack"); // NullPointerException

予期しないNullPointerExceptionが起こります。というのも、myName参照変数は、nullを指していて、nullにequalsメソッドを適用できないからです(equalsはStringクラスのメソッドですから)。

なぜ、予期しなかったのでしょうか?たぶん、BankAccountのインスタンス生成時にholder nameも一緒に初期化して、あるいは、初期化した後に、すぐにaccountHolderNameに値をセットしたと想定したからでしょう。もちろん、equals()メソッドをmyNameに適用する前に、nullをチェックしたり、try/catch構文を用いることもできます。

if (myName != null) {
myName.eqauls("Mr.Hack");
}

try {
myName.equals("Mr.Hack");
}
catch (NullPointerException e) {
// NullPointerExceptionの場合のロジック
}

しかしながら、参照型(Stringなどのクラス)のメソッドを使う前に、その参照変数全てに、nullをチェックしていたら、とても大変な労力になってしまいます。それより、インスタンスを生成時に、nullは許さない、という約束事をしておけば、わざわざ、BankAccountクラスのインスタンスを利用する時、nullをチェックしなくてよいですね。

class BankAccount {
private double balance;
private String accountHolderName;
/**
* コンストラクタ。accountHolderNameと balanceの値を初期化する。
* ただし、accountHolderNameはnullは許されない。nullをセットした場合は、 * IllegalArgumentExceptionをスロー。
*
* @throws IllegalArgumentExceptoin accountHolderNameにnull
* をセットした場合
* @param accountHolderName 預金者氏名
* @param balance 預金残高
*/
BankAccount(String accountHolderName, double balance) {
setAccountHoldername(accountHolderName);
setBalance(balance):
}

public void setBalance(double balance) {
this.balance = balance;
}
public double getBalance() {
return this.balance;
}
/**
* 預金者氏名をセットする。預金者氏名の文字列がnullの場合、
* IllegalArgumentExceptionをスロー。
*
* @throws IllegalArgumentException 預金者氏名がnullの場合
*/
public void setAccountHolderName(String accountHolderName) {
if (accountHolderName != null) {
this.accountHolderName = accountHolderName;
}
else {
throw new IllegalArgumentException ("The value is null");
}
}
public String getAccountHolderName() {
return this.accountHolderName;
}
}

この場合は、BankAccountインスタンスを生成する時は、必ず、accountHolderNameとbalanceをセット(初期化)しなければなりません。

BankAccount account = new BankAccount("Mr.Hack", 1000.0);

そのため、new で生成されたBankAccountインスタンスが存在する = accountHolderNameとbalanceには、何かしらの値がセットされている、ということがいえるわけです。なぜなら、2つのパラメータなしには、BankAccountインスタンスを生成できないからです。そのため、BankAccountインスタンスを使うクライアント側では、安心して、StringであるmyNameにStringメソッド(equals, indexOf等)を適用できるようになります。

実は、大規模なプログラムを組んでいくと、コンストラクタを使わない場合、(デフォルトのコンストラクタは使うことになりますが)、初期化忘れが、多々起こり得るのです。

というわけで、要約しますと、コンストラクタは、必要な値を、初期化するために存在するということができます。


> でもそのあとのコンストラクタはなぜ this(accountId, password,
> 0);としてaccountIdやpasswordのチェックをしていないのでしょう か?

いい質問だと思います。こうすれば、わかりやすいと思います。

コンストラクタに3つのパラメータがある時は、accountIdとpasswordが適切かどうかチェックしていますね。

public BankAccount(String accountId, String password, double amount) {
//不適切な文字列の時IllegalArgumentExceptoinをスロー
setAccountId(accountId);
//不適切な文字列の時IllegalArgumentExceptoinをスロー
setPassword(password);
setBalance(amount);
...
}

それでは、パラメータが二つの時、つまり、パラメータがaccountIdとpasswordだけの時、

public BankAccount(String accountId, String password) {
//不適切な文字列の時IllegalArgumentExceptoinをスロー
setAccountId(accountId);
//不適切な文字列の時IllegalArgumentExceptoinをスロー
setPassword(password);
setBalance(0.0);
...
}

とすれば、accountId、passwordをそれぞれsetterメソッドでチェックしていますね。この場合は、balanceはどんな状況でも、0.0をデフォルトとしてセットしています。しかしながら、上の2つのコンストラクタは、パラメータの数と、setBalanceのパラメータ以外は全く同じことをしています。これをもっと、効率よくできないでしょうか?それが、thisキーワードです。ここで、thisは、すでに存在するコンストラクタを指しますので、thisを使えば、上の最初のコンストラクタを呼び出すことができます。

public BankAccount(String accountId, String password) {
this(accountId, password, 0);
}

これは、最初の3つのパラメータのコンストラクタを呼んでいて、その3つのパラメータのコンストラクタのなかで、accountIdとpasswordをチェックしてるので、事実上、thisを使っても、accountIdとpasswordをチェックしていることになります。

このthisを使う方法は、パラメータの数が違うコンストラクタを何個か作らなければならないが、コンストラクタの役割がほとんど同じ場合には、有効です。

ただ、thisというキーワードはコンストラクタとしての役割もありますが、むしろ、インスタンスとして使われる場合の方が多いので、インスタンスとしてのthisも一緒に覚えておくことをおすすめします。

例:

public void setAccountHolderName(String accountHolderName) {
//ここのthisはインスタンスのthis
this.accountHolderName = accountHolderName;
}

それでは、皆さん、12月中旬にまたお会いしましょう。

Mr.Hack

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



© 2002 MR.HACK ALL RIGHTS RESERVED