読書会(Javaの格言)第2回議事録
[ 戻る ]
< 読書会(Javaの格言)第2回議事録 >
2000/07/16
文責 田中良和
□ 日時: 2000/07/15(土)10:00から16:00まで
□ 場所: Orangesoftさんの会議室
□ 参加者: 遠藤さん、橋本さん、鷲崎さん、野村さん、田中、野中さん、
石黒さん、布留川さん、西海さん、高橋(徹)さん、塩田さん、高岡さ
ん
□ 当日のスケジュール
1. 自己紹介
2. 書記、読み手の選出
3. 読書
4. 昼食
5. 読書
6. 2次会(有志)
□ 第4章 型の安全性と定数
「序論」
◇ 定数オブジェクトの使い方を考察し、実行時エラーの発生を縮減するイディオムを
紹介する。
「定数について」
◇ 定数にするためにfinal修飾子(初期化は可能だが、それ以降の代入は不可。)で宣
言する。同時にstatic修飾子(クラス変数)で
宣言することもある。
◇ enumの発音は、イーナム? イニューム? 語源はenumerasion[イニューメレイシ
ョン]。
◇ enumの構文は?
enum color { white red black }
0 1 2 (デフォルトの定数)
◇ enumをJavaに含めなかったことが賢明か?
enumは下記のような場合、困るのではないか。
元のenum 拡張したenum
----------------------- 不整合× -----------------------
| こっちでは red = 1 | ----------> | こちらでは red=2 |
----------------------- -----------------------
コンパイル済み コンパイル済み
◇ 「ブランク」finalは正式な呼び名か?
そのように呼んで良い。
◇ 型に安全な定数の作り方
1.クラスをfinalとする。
2. コンストラクタはprivateとする。
3.自己と同じ型のインスタンスを保持する。
しかし、この方法では、nullをコンパイラが見逃してしまう。
定数として状態をもつnullなのか?それともエラーとしてのnullなのか?判断でき
ない場合がある。
◇ AlienRace.BORG と AlianRace.FERENGIは映画スタートレックに登場する種族である
。
◇ 定数を表す代理(プロキシ)オブジェクトを使うことによって、定数の状態と値を
実行時に変更できる。よって、p.80の例題にお
いては、getValue()の呼び出しによって、定数の状態がnullのとき、0を返す。しかし
、プロキシオブジェクトをわざわざ使うことに
不満あり。nullの場合は例外を投げるというルールにすれば、プロキシオブジェクトは
不要ではないかという意見が多数だった。
◇ 80対20のルールとは?
・ ある学者の講義の80%について、20%の受講者が質問してくる?
・ 会社の利益の8割は、2割の職員がした仕事の見返りである?
・ HotSpotの処理は、手間がかかっているところを速くし、全体として早く実行
させるというものだ。
「変更不能オブジェクト」
◇ 例としてjava.lang.Stringがある。String型をメソッドの引数とするときは、無意
味な代入を防止するために、引数をfinal宣言す
る。または、ローカル変数をfinal宣言する。
◇ p.84の例は、メソッド内部で無名インナークラスをインスタンス化する場合は、引
数をfinalにするか、ローカル変数をfinalにし
なければ、コンパイルエラーになるというもの。これは、「変
更不能オブジェクトの例」というよりもむしろ「final繋がり」の例である。
◇ pp.85,86の例題はメソッドの引数をfinalにしてあるが、メソッド内部で引数のオブ
ジェクトが変更されているというもの。この副
作用から逃れるために、読みとり専用interfaceを使うか、
clone生成を利用する。
「読みとり専用のinterfaceをimplementsする」
◇ p.89の7行目に誤植あり。ReadOnlyPael × ----------> ReadOnlyPanel ○
◇ 読み取りしか出来ないinterfaceを作り、これを引数または返り値の型とする。
「クローン生成」
◇ クローン生成はよく使われるのか?という意見があり、高橋さんがRMIでオブジェク
トのコピーを配るシステムを作っていたとき、
1つのコピーの変更が他のコピーにも影響したため、
Cloneableインターフェイスを実装したという経験を語る。
◇ C++のコピーコンストラクタは難しかった。
◇ Objectクラスにはprotected native clone()メソッドがある。しかし、java.lang.Cl
oneableインターフェイス(中身は空っぽ)を
実装していないので、デフォルトのObject.clone()は、
CloneNotSupportedExceptionを投げる。clone()をオーバーライドするときは、super.cl
one()を記述する必要であることに注意。
◇ 浅いコピーと深いコピーの違いについて
フィールドがオブジェクトである場合
・浅いコピーはクローンされたオブジェクトも同一の参照を持ってしまう。
・深いコピーはフィールドのオブジェクトに対してもclone()を呼び出すように
自分で実装することで、異なる参照を持つこと
が出来る。
「クローン生成可能な読み取り専用オブジェクト」
◇ pp.97,98の例題では、委譲による方法を採用することによって、引数のオブジェク
トの変更が副作用を起こさせるようなコードは
書けない。
◇ 継承による方法では、以下の通り、オブジェクトの変更が予期せぬ変更を生じさせ
るコードが書けてしまう。
--------------- ------------------------
| Calender | | ReadOnlyCalender |
--------------- ------------------------
△ △
| |
| |
| |
---------------------------------------
| ReadOnlyCalenderImpl |
---------------------------------------
PrintNextDaysDate(ReadOnlyCalender date)
{
Calender calCopy = (Calender)date;
CalCopy.roll(Calender.DATE, true); // 変更してしまう。
}
「まとめ」
◇ ペダンチック:識者ぶる、知ったかぶりの意
□昼食
□第5章 例外
「序論」
◇ Javaに移行してきた人がコンパイラに叱られて困惑するところ、Javaは例外処理を
強制される言語である。
◇ Error とException の英語のニュアンスは?
Error の同義語;mistake, oversight, inaccuracy, slip
Exceptional の同義語;unusual, different, strage, irregular, abnormal
「Javaの例外」
◇ ユーザ定義の例外とJava環境が備えている例外の2つがある。
◇ p.106の「点火プラグ」? 英語のギャグか? exitするまで呼び出しスタック上の
各メソッド中に適切な関数が無いかチェックが
連続的に続くことの喩えでは?
「例外を定義する」
◇ すべての例外はjava.lang.Throwableのサブクラスである。
◇ コンストラクタに渡されるString型のパラメータは当該の例外の理由と見なせる。
「例外を処理する」
◇ その例外をどうしたいのか。
1.呼び出し側のメソッド中で例外を処理する。 ----> try, catch, finally
2.例外処理の責任を呼び出しスタックの上方向に引き渡す。 --->
戻り型 メソッド名(パラメータ) throws
例外型のリスト
◇ 致命的な例外と回復可能な例外とでクラス階層を分ける。
◇ 型に安全な定数(ここでは、DbFaltクラス)を使うことによって、例外クラスの数
を少なくすることができる。
◇ pp.118の例では、throw ex; によって、getEmployees(); から例外が投げられた旨
が報告される。他方、throw
(RecoverableDatabaseException)ex.fillInStackTrace(); で例外の情報
を更新することによって、ラップしているメソッドtestGetEmployees()から投げられた
ことになる。
◇ 単一入り口/単一出口の例は余計ではないか?構造化プログラムでも出口は複数ある
のではないか?という意見があった。
「finally」
◇ 「原則」は文中のどこを指しているのか?「例」は意図が分かりにくい。という意
見。
「コンストラクタ中での例外について」
◇ 一般的にコンストラクタ中には例外を実装しないことになっているのか? newした
ら、普通はインスタンス化されたオブジェクト
が返されると思うだろう。例外が返されるとは思わないだ
ろう。
「例外の不適切な使い方」
◇ 案外、ウケた。
◇ C++が出たての頃、コンストラクタにすべての処理を書く人もいた。
「委譲ベースの例外処理」
◇ 3章のダブルディスパッチの仕組みを想起することは、ほとんど正解、ちょっと違
う。
◇ 例外ごとにcatch文を書かないで、ExCmdDispatcher.classに例外ごとの処理を任せ
る。
◇ ピーター・コードの本にも「通知を利用した処理」について同様のことが書いてあ
る。
◇ ハンドラーとディスパッチャクラスは別々に作成できるので、ハンドラーにおいては
GUIの処理へも簡単に移れる。
□休憩15分間の話題
◇ Javaのクラスライブラリ中に、ダブルディスパッチの例はあるか? イメージが湧
かない。
◇ ダブルディスパッチのような間接的なコードがすらすら書けるようになるのだろう
か?
◇ サーブレットによるアプリケーションを開発中。いろいろなユーザーにポリモルフ
ィズムを使って多彩なサービスをしたい。
□第6章 コールバック
「序論」
◇ 話したい相手に繋がりにくい電話を例としている。
1.後でかけ直す。 -------------------> ポーリング
2. つないだままにする。 -------------> 同期メソッド呼び出し
3. 折り返し電話をくれるように頼む。----> コールバック
「ポーリング」
◇ p.137の4行目に誤植あり。SocketClient × --------> StockClient ○
「コールバックのしくみ」
◇ 先ほどの電話の例を使用して、
Caller; 先に電話をかけた方、つまり、通知を依頼して通知を待つ方。
Receiver; 通知の依頼を受けて、callerへ通知する方。
◇ 図6.1はシーケンス図である。インタラクション(相互作用)図には、もう一つ、コ
ラボレーション図というものがある。
◇ 矢印の先端が半分なのは、非同期呼び出しを表す。
「コールバックを実装する」
◇ シーケンス図の上部の表現について、
1.オブジェクト名:(コロン)クラス名
2.インスタンスを表すときは全体の文字列にアンダーバーを引く。
3.オブジェクト名は省略可。
◇ ここでは一つのStockClientオブジェクトをセットするので、p.142の1行目、addSto
ckListener よりも setStockListnerの方がよ
り適切ではないか。JavaBeansの命名規則では、1つのリスナにイベントを送信するよ
うに登録するには、 setListener(Listener) とする。複数のリスナ登録の場合、
addListener(Listener)。
◇ 図6.2における四角内は、左から :Application stockClient:StockClient :St
ockServer 。
「マルチキャストコールバック」
◇ SLHolderというヘルパークラスを追加することで前節の例を改良して、複数のクラ
イアントへの通知を可能にした。
◇ JAVAHOUSEでは、「Javaにおいてはコールバックは当たり前のパターンなので、こと
さらにコールバックと呼ぶのは止めよう。」と
いう意見があった。
◇ pp.145-147の例では、stockListeners_ に対して、run()やaddStockListner()等に
おいてsynchronized宣言しているので、run()実
行中にaddStockListener()が呼び出された場合にデ
ッドロックするのではないか。
「コールバックと例外処理」
◇ ExceptionListenerをStockListenerとは別に作るべきではないか。
[ 戻る ]