Back To Main

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

◆目次◆

【前編】
■BankUserInterface.java
■BankUserInterfaceの作り方
■預金・引き出し前の残高表示

◎【後編】
■預金の問い合わせ(預金なしは0を得る)・残高表示
■引き出しの問い合わせ(引き出しなしは0を得る)・残高表示
■プログラム終了か否か
■IOExceptionのキャッチ
■BankAccountクラスを使わなかった理由
■Question 10

前編からの引き続きです。


■預金の問い合わせ(預金なしは0を得る)・残高表示
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ユーザーに入力を促すメッセージ『預金額を入力して下さい(預金しない場合は0を入力): 』を表示した後、ユーザーから数値を得たいですが、どうすれば良かったのでしたっけ?どうすれば、ユーザーから数値を得ることが出来ますか?ConvertToCelsiusでは何を使いました?

そうです。BufferedReaderクラスを使いましたね。

┌──────────────────────────────────┐

BufferedReader buffer = new BufferedReader(
new InputStreamReader(System.in));

└──────────────────────────────────┘

は、皆さんにはおなじみですね。いったんbufferを得ることが出来れば、後はEnterキーを押すまでの文字列は、buffer.readLine()で取り出せます。

┌──────────────────────────────────┐
double depositAmount = Double.parseDouble(buffer.readLine());
└──────────────────────────────────┘

とdouble型のdepositAmountを得ます。ここで、depositAmountの値によってプログラムを分岐します。もしdepositAmountがゼロの場合は、宿題で、『ユーザーがなにも預金しない場合は0を入力させる』と与えられているので、BankAccount#deposit()を呼び出さないようにしないといけませんね。もし、ゼロをdeposit()に渡したら、IllegalArgumentExceptionが発生します(API参照)。例外が発生すると、ゼロとマイナスで発生するExceptionクラスを分けていませんから(両方ともIllegalArgumentExceptionが発生)、それが発生した場合、どれがゼロのIllegalArgumentExceptionか、どれがマイナスのIllegalArgumentExceptionか分かりません。つまり、マイナスの場合だけ、『不正な入力です。数値を入力して下さい :』とメッセージを表示することができません。そのため、deposit()メソッドを呼び出すまえに、if文でdepositAmountが0か否かのチェックが必要です。以下が預金のロジック部分です。

┌──────────────────────────────────┐

System.out.print("預金額を入力して下さい(預金しない場合は0を入力): ");
// ユーザーが適切な数値(数値でマイナスではない値)を入力するまで
// ループ
while (true) {
try {
// double型の値を取得。数値でない場合NumberFormatExceptionをスロー
double depositAmount = Double.parseDouble(buffer.readLine());
if (depositAmount != 0) {

// 以下の6行中、BankAccountクラス取得後、3行は削除、
// その後の2行のコメントをとり、最後の1行は削除
System.out.println("");
System.out.println("Call: deposit()メソッド deposit amount:" +
depositAmount);
System.out.println("Call: getBalance()メソッド");
// bankAccountObject.deposit(depositAmount);
// balance = (int) bankAccountObject.getBalanace();
balance = (int) depositAmount;

}
break; // 例外が発生しなければ、whileループを抜ける
}
// Double#parseDouble()がスロー
catch (NumberFormatException e) {
System.out.println("");
System.out.print("不正な入力です。数値を入力して下さい : ");
}
// BankAccount#deposit()がスロー
catch (IllegalArgumentException e) {
System.out.println("");
System.out.print(e.getMessage() + "もう一度入力して下さい : ");
}
// BufferedReader#readLine()がスロー
catch (IOException e) {
throw e;
}
}

└──────────────────────────────────┘

ここのプログラムのミソは、例外発生をうまく利用していることです。例外が発生しない場合だけ、breakキーワードで、whileループを抜ける仕組みになっています。ちなみに、while (true)という部分は、無限ループといいます。
というのは、whileのexpression部分は常にtrueというキーワードですね。つまり、いつも式はtrueと評価されますので、永遠とループすることになります。このほかに形態として、for (;;)という形もあります。

例外発生について言いますと、まず最初に、BufferedReader#readLine()がIOExceptionを発生する可能性があります。もし発生したら、try/catch構文でキャッチしますが、もう一度、そのキャッチしたeを外側のtry/catchでキャッチして、『不正な処理を行ったため、プログラムを終了します』と表示させます。これは、後で説明します。

二番目に例外が発生する可能性は、Double#parseDouble()です。これは、ユーザーがnumeric character(0-9からなる文字)を入力しなかった場合にNumberFormatExceptionを発生します。そのときは、不適切な値なので、『不正な入力です。数値を入力して下さい : 』と表示して、もう一度whileループを実行します。

そして、最後に例外を発生する可能性があるのは、BankAccount#deposit()です。いまは、BankAccountクラスは使わないとしてあるので、コメントしてありますが、マイナス・ゼロの値をdeposit()に渡すと、IllegalArgumentExceptionが発生します。そのときは、発生した例外メッセージと『もう一度入力して下さい : 』を表示し、もう一度whileループを実行します。

皆さんは、もうすでに、例外処理をちゃんと勉強しましたので、これぐらいのtry/catch構文ではびくともしませんね。簡単に感じるでしょう?ただ、どこのメソッドがどの例外を発生しているかが分からないと難しく感じるかもしれません(それ故、自分でAPIを作成するときは必ずRuntimeExceptionも含め、@exceptionタグを使って説明するのでしたね)。

僕は、超ビギナープログラマだった頃、プログラムを書いているときに一番苦手に感じたのが、try/catch構文でした。いまいち仕組みも分からず、何でわざわざスローするのかさえ、分かりませんでした。しかしながら、いったんこのtry/catch構文の意味わかると、とても便利なツールになります。皆さんは、是非例外処理のプロフェッショナルになってくださいね。例外処理で分からなくなったらこのメルマガのバックナンバーをもう一度読んでみて下さい。そして、それでも分からないときは、掲示板から僕に質問して下さい。

■引き出しの問い合わせ(引き出しなしは0を得る)・残高表示
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

これは、考え方は、預金の問い合わせと全く同じなので省略します。


■プログラム終了か否か
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

さて、預金・引き出しが終わった後、引き続き預金・引き出しを行うか、または、プログラムを終了するかをユーザーは決めることが出来るようにしましょう。
ユーザーが入力したときに、適切な値ではない場合は、何度も適切な入力を促すようにしたいので、ループを使いましょう。

┌──────────────────────────────────┐

while (true) {
if (ユーザーがq、Qを選ぶ) {
break;
}
}

└──────────────────────────────────┘


上記のif文は、『choice == 'q' || choice == 'Q' ならば、break』というようにすると、q、Qをチェックできます。ここでchoiceは何型ですか?Javaでシングルコーテーション(')を使うとchar型を表します。つまり、'q'はchar型です。そうなるとchar型の'q'と比べることが出来るのは、char型のchoiceということになります(int型でも比較出来ます。char型'q'をint型に変換するとdecimalで何の数字でしょう?答えは、このメルマガの一番最後にあります(1))。if文の前に、事前にchar型の値を得て、それをchoiceに入れれば良さそうですね。

では、char型の値はどうやって得ればいいでしょうか?

buffer.readLine()でString型の値を得ましたね。Java SDK API仕様にいってみてください。char型を得るにはどのメソッドを使用すればいいでしょうか?

お、メソッドの概要の一番最初にありました。返却型がcharであるのは、charAt()メソッドですね。APIを調べるのはここだけで終わってはいけませんよ。charAt()のリンクを必ずクリックして下さいね。もしかしたら、例外を発生するかもしれませんからね。発生するとしたらどんな例外ですか?引数としてint indexを渡すので、適切なインデックスを渡さないと、プログラマのエラーで発生するRuntimeな例外が発生しそうだ、と推測するのですよ。インデックスの値によって発生する・しないの例外は実行時の例外です。では、クリックして下さい。

ほら、IndexOutOfBoundsExceptionでしたね。JavaはC/C++とちがって、配列にアクセスする場合(配列のインデックスは0から配列のサイズ-1)は、マイナスや配列のサイズと同じ値のインデックス以上を渡すと、IndexOutOfBoundsExceptionというランタイム(実行時)の例外が発生します。

ランタイムの例外といわれても、もう怖くないですね。そうRutimeExceptionを継承しているクラスですね。ですから、実行時に例外が発生するのです。これは、checkでしたっけ?uncheckでしたっけ?(分からない人はバックナンバー参照かメルマガの一番下を参照(2))。

String#charAt()メソッドを見ると、

┌──────────────────────────────────┐

指定されたインデックス位置にある文字を返します。インデックスは、0 〜
length() - 1 の範囲になります。配列のインデックス付けの場合と同じよ
うに、文 字列の最初の文字のインデックスは 0、次の文字のインデックス
は 1 と続きます。

└──────────────────────────────────┘

とあります。つまり、

┌──────────────────────────────────┐

String myString = "Mr.Hack";
char character = myString.charAt(0);

index
0 1 2 3 4 5 6 7
M r . H a c k \n

└──────────────────────────────────┘

とすると、'M'という値が、characterに格納されます。『\n』は文字列の終わりを表すエスケープシーケンスで、index 6までがmyStringです。このcharAt()メソッドを利用して、

┌──────────────────────────────────┐

try {
char choice = buffer.readLine().charAt(0);
if (choice == 'q' || choice == 'Q') {
isContinued = false;
break;
}
}
// String#charAt()でスロー
catch (IndexOutOfBoundsException e) {
...
}

└──────────────────────────────────┘

と出来そうです。if文の中のboolean型のisContinuedは外側のwhileループを続けるか続けないかのトグル(続けるか続けないかのスイッチ)なので、falseを代入して、次の外側のwhileループの式評価に備えます(whileループの式はfalseと評価されるので次回は外側のwhileループを抜け出すことが出来る)。

設問では、『 h)qかQをタイプした場合のみ、プログラムを抜ける。』となっているので、qとQをタイプした場合のみbreakするようにすればいいですね。それ以外のキー入力は全てもう一度、預金・引き出しを続けるようにする場合は、

┌──────────────────────────────────┐

try {
char choice = buffer.readLine().charAt(0);
// choiceが 'q'、'Q'のとき
if (choice == 'q' || choice == 'Q') {
isContinued = false;
break;
}
// choiceがそのほかの文字のとき
else {
isContinued = true;
break;
}
}
// choiceが空文字のとき
catch (IndexOutOfBoundsException e) {
isContinued = true;
break;
}

└──────────────────────────────────┘

とします。僕は、エンターキーを押した時だけ、もう一度預金・引き出しを続けられるようにし、'q'、'Q'以外のどんな文字も『不正な入力です。QまたはEnterキーを押して下さい : 』としてユーザーにもう一度入力を促すようにしました。それが以下のパートです。

┌──────────────────────────────────┐

try {
char choice = buffer.readLine().charAt(0);
if (choice == 'q' || choice == 'Q') {
isContinued = false;
break;
}
else {
System.out.print("不正な入力です。" +
"QまたはEnterキーを押して下さい : ");
}
}
catch (IndexOutOfBoundsException e) {
isContinued = true;
break;
}

└──────────────────────────────────┘

ところで、Enterキーを押した場合は、buffer.readLine()は空文字列ですのでcharAt(0)を使うと、IndexOutOfBoundsExceptionがスローされます。その仕組みはどうなっているかといいますと、以下の例を考えてみて下さい。

┌──────────────────────────────────┐

String myString = "";
//実行時の例外(RuntimeException)発生
char character = myString.charAt(0);

index
0
\n

└──────────────────────────────────┘

空文字列の場合、インデックス0にはアクセス出来ませんね。インデックス0はインデックスの範囲外(out of bounds)なのです。つまり、空文字列の時にcharAt(0)を使うと、IndexOutOfBoundsExceptionが発生します。

今回はその例外が発生した場合だけ、引き続き預金・引き出しが出来るようにしました。もちろん、エンターキー以外でも預金・引き出しが出来るようにしてもいいですよ。

┌──────────────────────────────────┐
charAt()メソッドでchar型の値ををチェックしないで、String型の値を
そのままチェックしたいのだけど?
└──────────────────────────────────┘

いいですよ、それも可能です。char型でチェックするのではなく、String型でチェックしてみましょうか?これは、今週の宿題で挑戦してみましょう。

■IOExceptionのキャッチ
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

さて、先ほど預金をするロジックのところで、BufferedReader#readLine()がIOExceptionを発生する可能性があります、と書きました。その場合の対処方法ですが、buffer.readLine()でIOExceptionの例外が発生したら、リカバリーは難しいと思います。ですから、それが発生したら、whileループを途中で中断して、『するべきこと』をして、直ちにプログラムを終了するのが賢明な選択だと思います。『するべきこと』とは、プログラムを終了する前に、bufferストリームを閉じてあげることですね。それには、try/catch/finally構文を使うと以前述べました。つまり、

┌──────────────────────────────────┐

try {
IOException発生
}
BufferedReader#readLine()がスロー
catch (IOException e) {
//プログラム終了
return;
}
finally {
try {
buffer.close();
}
catch (IOException e) {
System.out.prinltln("ストリームクローズ中に例外が発生しました");
}
}

└──────────────────────────────────┘

finallyを使えば、buffer.close()を必ず実行できましたね。普段は、finallyはcatch節の後に実行されますが、catch節が、return、continue、breakキーワードを含んでいるときは、そのキーワードの前に実行されます。つまり、returnでmain()メソッドを終了する前に、上記の部分で、buffer.close()が必ず実行されることになります。

ところで、各預金・引き出し・プログラム続行のところでIOExceptionをtry節でキャッチするたびにfinally節を使うと合計で3回使わないといけなくなりますね。例えば、預金のロジックで、

┌──────────────────────────────────┐

try {
// 預金ロジックの中でbuffer.readLine()を実行

}
// Double#parseDouble()がスロー
catch (NumberFormatException e) {
System.out.print("不正な入力です。数値を入力して下さい : ");
}
// BankAccount#deposit()がスロー
catch (IllegalArgumentException e) {
System.out.print(e.getMessage() + "もう一度入力して下さい : ");
}
// BufferedReader#readLine()がスロー
catch (IOException e) {
return;
}
//これ以下の部分を毎回書かなければならない
finally {
try {
buffer.close();
}
catch (IOException e) {
System.out.prinltln("ストリームクローズ中に例外が発生しました");
}
}

└──────────────────────────────────┘

しかし、IOExceptionキャッチ節でreturnする代わりにそのまま、eをスローしてあげます。

┌──────────────────────────────────┐

catch (IOException e) {
throw e;
}

└──────────────────────────────────┘

そのスローされた、eはどこでキャッチするのですか?キャッチするtry/catch/finally構文を外側のwhileループにもうけてあげて

┌──────────────────────────────────┐

try {
while (isContinued) {

while (true) {
try {
// 預金ロジック、buffer.readLine()でIOException発生
}
catch (IOExcetpion e) {
throw e; //キャッチしたIOExceptionのeをもう一度スロー
}
...
}
...
}
}
catch (IOException e) {
return; //main()メソッド終了
}
finally {
try {
buffer.close();
}
catch (IOException e) {
System.out.prinltln("ストリームクローズ中に例外が発生しました");
}
}

└──────────────────────────────────┘

とします。こうすれば、finally節の記述は一回ですみますね。ところで、内部のwhileループで

┌──────────────────────────────────┐

catch (IOExcetpion e) {
throw e; //キャッチしたIOExceptionのeをもう一度スロー
}

└──────────────────────────────────┘

としましたが、実際には、catch節は記述しなくても大丈夫です。というのは、外側のtryでIOExceptionをキャッチしてくれるからです。上記のcatch節があるとbuffer.readlLine()でキャッチしたIOExceptionを、もう一度スローして外側のtry/catch構文でキャッチすることになるので、余分な記述ですね。しかしながら、分かりやすいように今回はこうやって記述しました。読みやすさを考えると余分でも記述した方がいいかもしれません。


■BankAccountクラスを使わなかった理由
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

最後に、今回BankAccountクラスを使用しなかった理由を見てみましょう。それの最大の理由は、コンソールベースのユーザーインターフェイスに集中してもらうための練習です。今の段階では、クラスは、BankAccountクラスとそれのユーザインターフェイスであるBankUserInterfaceクラスしかありません。BankAccountクラスも難しくないので、すぐに完成させることが出来るでしょう。しかし、もしこれが、データ構造を実装してlinkedlistを使ったり、データベースに接続していたらどうしましょう?それらのクラスが完成するまで、BankUserInterfaceクラスは実行出来ませんね。実行できないということは実際にユーザーインターフェイスがちゃんと動いているか確認も出来ないということです。それでは、こまりますね。自分一人でこのプロジェクトを担当している場合は、全てのロジック部分のクラスを完成してはじめて、ユーザーインターフェイスのチェックが出来ます。このプロジェクトに他の人が関わっていれば、他の人のクラスが完成してはじめて、ユーザーインターフェイスを担当しているあなたは、BankUserInterfaceクラスをチェックできるのです。今回は、バックグランドのロジックに頼らずに、ユーザーインターフェイスだけでコンパイル実行出来るようにしました。

ところで、そもそもユーザーインターフェイス(UI)とはどういう役目なのでしょうか?ユーザーから値をもらって、その値を他のクラスのメソッドに渡してあげることも一つの役割です。それよりも重要なのは、ユーザーがしたいことを的確に実行できるようにしないといけません。たとえば、預金したいのであれば、預金するロジックを呼び出してあげます。途中で預金するのをやめたくなった場合は、やめられるような方法(例えば、qを押したら預金終了のような方法)を選択肢として示さないといけません。その選択肢をユーザーが望むように提示してあげるのがユーザーインターフェイスの役目なのです。ユーザーから得た値を加工・処理するのはバックグランドのロジック部が担ってくれます。UIはそのロジック部が要求しているフォーマットを用意してあげてさえいれば、十分なのです。例えば、BankAccount#deposit()がdouble型の正の整数を引数として要求していれば、それを用意してあげればいいのです。そこでユーザーインターフェイスの役割は終わりです。

あとは、BankAccountクラスが準備できれば、コメントをとって今までテスト用に表示してた数行をとれば完了です。たとえば、預金ロジックのところでは、

┌──────────────────────────────────┐

System.out.println("");
System.out.println("Call: deposit()メソッド deposit amount:" +
depositAmount);
System.out.println("Call: getBalance()メソッド");
// bankAccountObject.deposit(depositAmount);
// balance = (int) bankAccountObject.getBalanace();
balance = (int) depositAmount;

└──────────────────────────────────┘

コメントしてある行のコメント、//をとって、Systemから始まる行3つと、最後のbalance = (int) depositAmountを削除してあげれば、完成するはずです。もちろん、deposit()メソッドを使う前に、BankAccountのインスタンスbankAccountObjectを初期化してあげないといけませんね。

この件に関しては、掲示板でも扱っているので、参考にして下さい。とても熱心な読者の方から質問をいただきましたので、そこにも今回のヒントがあると思います。その方のように、メルマガ発行までに実際取り組むということは素晴らしいとおもいます。実際に自分で考えて見ないと、分からないところが分からないままだと思います。ぜひ、分からないところを分かって、自分で調べるなり、掲示板で質問するなりしてみて下さい。皆さんの学力がアップすること間違いなしだと思います。

それでは、今週の宿題にいってみましょう。

■Question 10
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1.BankAccountクラスを実装して、実際に預金・引き出し・残高が正常に作動しているかどうか確認しなさい。

2.BankUserInterface.javaを以下のように変更しなさい。

a) 一連の預金・引き出し・参照というプログラムの流れから、
以下のメニュを作りなさい。

1.預金する
2.引き出す
3.残高参照する
4 取引を終了する

※メニュー選択は1-4の数字にする。他の値、文字、空文字もチェックし、
適ではないときは、その旨を表示する。

b)各項目を選択すると、それぞれのロジックを実行するようにしなさい。
例:

1.預金するメッセージを表示する("預金額を入力してください")
2.預金メソッドを呼び出す
3.預金後の残高を表示知る("預金後の残高はxx円です")
4.メインメニューに戻る

3. 2のメニュー4で取引を終了するときに、本当に終了するかの旨(取引を終了してもよろしいですか?)を表示し、'y'、'Y'を選んだ場合プログラムを終了し、'n'、'N'を選んだ場合は、メインメニューに戻るようにしなさい。また、そのロジックをisContinued()メソッドとして独立させなさい。メソッドの仕様は以下の通り。文字(列)をチェックするときは、Stringクラスを使いなさい(char型では比較しないようにする)

1.定義:boolean isContinued();
2.ユーザーが'y'、'Y'を選んだときtrueを返却
3.ユーザーが'n'、'N'を選んだときfalseを返却
4.それ以外の時もう一度入力を求める

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

ヒント:

今回は、前回のユーザーインターフェイスの発展系です。ユーザーインターフェイス作成チームに入ったあなたは、預金・引き出し・残高参照を一連にするプログラムを書きました。しかしながら、毎回、預金・引き出し・残高を参照するのは、どうも不便ではないかと、テストするチームからクレームがきました。預金・引き出し・残高参照を別々の個別メニューにしたらどうかと提案されました。
さて、あなたは、メニューの分岐にswitch文を使おうと思い立ちました。ユーザーからの入力された値が分かれば、

┌──────────────────────────────────┐

char choice = 入力された文字;
switch (choice) {
case '1':
//預金ロジック
case '2':
//引き出しロジック
....
}

└──────────────────────────────────┘

とロジックを分岐出来そうです・・・。また、ユーザーからYes Noをの意思を求めるロジックはどこでも使えそうなので、一つisContinued()というメソッドを作ることにしました。前回は、char型の値をチェックしましたが、ユーザーから"yes"や"no"と入力されるとchar型の値をチェックする方法は使えなさそうです。String型を比較するには、とJava SDK API仕様のStringクラスを見ると・・・。あるではありませんか、あるメソッドが・・。

1では、BankAccountクラスを実装してみてください。BankAccount.javaを同じフォルダにおいて、BankAccountクラスのコメントをとってダミー用のプリントアウト文を削除すれば、出来ると思います。

2では、分岐メニューをswitch文を使うと、プログラムを書きやすいと思います。不適切な文字もチェックするので、swich文をwhileループの中に書かないといけないでしょう。

3では、isContinued()メソッドの中で、buffer.readLine()メソッドを書かないといけないでしょう。その場合、bufferもそのメソッドの中で、初期化してもいいかもしれません。


皆さんの中には、そろそろ五月病にかかってやる気がなくなってしまったり、仕事や学校が忙しくなってとてもメルマガについていけないという方もいらっしゃる頃ではないかな、と思います。このメルマガのここが分からない、つまらない、ためになったなどの感想を聞かせて頂けるととても助かります。読者数があわせると1000を超えましたが、読者からの感想や意見を参考にメルマガに反映出来ればいいなと思っております。難しすぎてついていけないとか、言っていることが分からない等の感想は率直に受け止めて行かないといけないと思っています。一回分のメルマガが長すぎて読む気になれないという意見があるのであれば、それも考慮して行かなければならないと思っています。こういった意見を反映出来るのが、市販の書籍と違う長所だと思いますので、どうぞお気軽にメール頂けると幸いです。こういった題材を扱ってほしい等のメールでも結構です。僕が知っている内容ならメルマガに取り入れて行こうと思っています。

それでは、またあいましょう。

Mr.Hack

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

【答え】
1. 113 (decimal)。char型 'q'をint型にキャストするとdecimalで113になります。Hexadecimalで71です。
2. RuntimeExceptionを継承している例外クラスは、unchecked(コンパイル時にチェックされない)例外です。


© 2002 MR.HACK ALL RIGHTS RESERVED