親子の断絶バグパターン
やたらとsuper、thisが使用されていて、どうも見てみると親クラスのメンバ使用には必ずsuper.が、自クラスのメンバ使用には必ずthis.が付いている。多分is-a関係について理解していなくて、あたかもコンポジションのように使っている感じ。
private、パッケージprivateメソッド内でのsuper.の使用を禁止するコーディングルールには何か弊害があるだろうか...
ダウンロードトークン
Safari BookshelfでダウンロードしたPDFはプロテクトがかかっていて、テキストをクリップボードに貼れない事が分かった。読んでいて重要個所をメモにコピーしたり、辞書ソフトに分からない単語をペーストしたりという事が出来なくて、かなり不便なので、自分にとっては、このダウンロード機能は使えないという結論に達した。結局アカウントをダウンロード無しのBasicに変更。これなら月々$10。
池上梅園
そろそろ福寿草が咲いているかと思ったのだけど、無かった。もうやめちゃったのかなぁ。水仙も無かったし。残念。
梅はまだまだだけど、園内には、ちらほらと人が。割と暖かかったし、読書にはいいかも。

20D EF70-200mmIS@153mm F13 1/45sec ISO100
唯一満開の椿。

20D EF70-200mmIS@170mm F5.6 1/200sec ISO200
梅は二週間後くらいかな。

20D EF70-200mmIS@130mm F13 1/60sec ISO100
咲いているのもあった。

20D EF70-200mmIS@200mm F4.0 1/640sec ISO100
かばんが帰ってきた
愛用していたTUMIのかばん、キャスターがついていてハンドルで引っ張るタイプなのだけど、キャスターがボロボロに磨り減ってしまったので交換してもらった。そうしたらハンドルの引き出しがものすごくしぶくなってしまって、もう一度預ける事に。結局ハンドルも無料交換になって帰って来た。2か月近くかかってしまったよ。しかしキャスターもハンドルもとても良い具合。なんか新品の頃よりもいい感じ。こういった部品も地道に改良されているようだ。
今日はテキーラビールというのを飲んでみた。メキシコとかのビールかと思ったらなぜかフランスだった。度数も5.9%と普通。なんかジンジャエールみたいだった。そういえばテキーラって飲んだ事無いかも。
Safari Bookshelf
オンラインでプリント機能でfineprintに出力、fineprintのまとめ印刷機能で章単位とかにまとめた後、PDFWriterに出力すれば、手間はかかるけどダウンロードトークン無しでPDF化出来る事に気付いた。
fineprintって知らない内にfineprint5になっていたのか。うちはまだWin2kだし、fineprint2000のままでいいや。
SDカードがとんだ
Zaurusで使っていたSDカードがとんだ。かろうじて読み込めたのでデータを退避。フォーマットし直したら、また使えるようになったけど、ん〜どうなんだろ。とりあえずプログラムの格納領域として使用。今となっては安くなった256MBのSD、当時はそうとう悩んで買ったからなんだかもったいなくて、捨てる気にならない。
/tmpの下
ライブカムの処理プログラムは単純にjava xxx&で起動していて、でもこれじゃさすがに二重起動とか停止とか面倒なので、起動時にあるパスにディレクトリを作成。作成できなければ停止。実行中にこのディレクトリが消されたら実行中止という感じにしてある。
で、ディレクトリなら/tmpの下に置いておいても消されないだろうと思ったら、しっかり消されていた。おかしいな他の古いディレクトリは消えてないのに。中身が空だと消されちゃうのかな。いや/tmpに置くのがそもそも間違いなんだけど。
こたつとっぷ
そういえば、自分が初めてコード書いたのも座椅子でこたつトップだったと思う。とにかく金が無かったからZ80に2114(だったかな)というRAM2つ(これで、なんと1k byteの大容量メモリーを実現! いや冗談でなく当時としては大容量だったのだ)。あとはLEDとスイッチを24個(アドレス16本にデータ8本)並べて、リセットスイッチにDMA(確かバスリクエストという名前だった)、書き込みスイッチしかなかった。
もちろんROMもROMライターも無かったから、ブートストラップなんて無くて、DMAをかけてCPUを止めておいて、0番地から命令を二進数で書いていく。終わったらリセットスイッチを押しながらDMAを解除。リセットスイッチを離すと、0番地から実行が始まるので、頃合いを見てDMAをかけてメモリーの中をのぞいて結果を確認する。
そんなんでも楽しかったな。いやたぶん今やっても楽しいと思うな。その後I/Oポート付けたりキーボード付けたり、ビデオカード付けたりしていったけど、最初の頃が一番楽しかった気がする。二進法表示だと、結果を見ても、すぐには分からない。頭の中で16進数に変換して「64だから100か!合ってる!」というタイムラグがなんだか妙に感動を高めてくれた気がする。かれこれ25年くらい前の話だ。
あの感動は、自作アンプから初めて音が出てくる時の感動に似ている。アンプを初めて作ったのは30年くらい前だけど、最初のアンプは音が出てきた感動も束の間、スピーカーから火が出て(DCバランスが狂っていたんだろう)、天国から地獄だったが...
寒い寒い
今日は大宮までパフォーマンスチューニングに出陣。駅から15分の道のり、風がビュービューと吹き付ける。大宮って風強いの? 群馬かと思ったよ。
割と早くに一段落ついて帰還。帰りは京浜東北線でのんびり。PC開いて英文をこねくりまわしていたら、隣に座っていた人が「ワタシ、エイゴワカルカラ、アドバイスシテアゲマス」声かけられるまで分からなかった。色々と教えてもらった。やはり定冠詞は難しい(true/falseにはaをつけるのだね。知らなかった)。でも、意味的に違う文になっちゃったりしたのもあった。一応意味を確認してくれるんだけど、
The Class.getResource() takes a connection string that represents the location of the resource.
「コノブンハ、ドウイウイミデスカ?」って、説明難しいよ。「getResource()っていうメソッドがあって、それが文字列の引数を取るのですが...」って普通の人には意味不明だよな。
今度外人が、日本語を書いていたら、アドバイスしてあげよう。ってそんな機会あるのか?
ダウンキャストを取り除くGenerics
ダウンキャストを取り除くためにGenericsを使うのってどうなんだろう。
public class Base implements Comparable<Base> {
public int compareTo(Base o) {
return 0;
}
}
確かにキャストが不要になるから、嬉しいって言えば嬉しいのだけど、継承すると破綻する。
public class Sub extends Base implements Comparable<Sub> {
public int compareTo(Sub o) {
return 0;
}
}
$ javac -cp . Sub.java
Sub.java:1: java.lang.Comparable を異なる引数 <Sub> と <Base> で継承することはで
きません。
public class Sub extends Base implements Comparable<Sub> {
^
エラー 1 個
結局、継承したら自分で共変メソッドを実装するしかない感じ。
public class Sub extends Base {
@Override public int compareTo(Base o) {
return compareTo((Sub)o);
}
public int compareTo(Sub o) {
return 0;
}
}
Java Generics and Collections
今日は時間が無かったけど電車の中で第三部を読んでみた。ワイルドカードを使ったイミュータブルの試みというのが面白い。
public class Test {
public List<? extends Integer> getResult() {
return Arrays.asList(1, 2, 3);
}
public static void main(String[] args) {
Test test = new Test();
List<? extends Integer> list = test.getResult();
list.add(1);
}
}
$ javac -Xlint:unchecked Test.java Test.java:11: シンボルを見つけられません。 シンボル: メソッド add(int) 場所 : java.util.Listの インタフェース list.add(1); ^ エラー 1 個
始めは正直、意味不明だった。"extends Integer"って、Integerはfinalですが、とか、List<? extends Integer>だったらIntegerと、そのサブタイプのインスタンスは入れられるんじゃないの? とか。
List<? extends Integer>っていうのは、仮にIntegerが継承可能でSubIntegerとかがあったら、List<SubInteger>の参照も保持できるってことだ。ここにIntegerのインスタンスを放り込むのは当然エラー(もちろん逆、つまりList<Integer>にSubIntegerを放り込むならok)。だからコンパイルエラーなのだ。で、それを利用してlistを変更不可にしているというわけだ。
もちろん、資料にもあるようにclear()とかremove()が防げるわけじゃないし、nullは素通りするので、これは止めましょうと書いてある。ただGenericsの理解を深めるという点では面白い例だ。
もちろんキャストで回避できるのだけど、unchecked警告が出る。
public static void main(String[] args) {
Test test = new Test();
List<Integer> list = (List<Integer>)test.getResult();
list.add(1);
}
$ javac Test.java
注: Test.java の操作は、未チェックまたは安全ではありません。
注: 詳細については、-Xlint:unchecked オプションを指定して再コンパイルしてください。
$ javac -Xlint:unchecked Test.java
Test.java:10: 警告: [unchecked] 無検査キャストです
検出値 : java.util.List<capture of ? extends java.lang.Integer>
期待値 : java.util.List<java.lang.Integer>
List<Integer> list = (List<Integer>)test.getResult();
これって、javacもデフォルトだと控えめに報告するから軽く見ていたのだけど(何せlintだし)、この資料を読んでみて、一部の例外を除けば、基本的には全部つぶしておかないといけないものだというのが良く分かった。さもないと、思わぬところで(その場所では明示的にはキャストをしていない)、原因不明のClassCastExceptionが起きてしまう。
Safari Bookshelf
Safari Bookshelfというのに申し込んでみた。月額$20払うと、10スロット分の場所がもらえて、そこに入る分だけの本をオンラインで閲覧、内容の検索などできる。本は1冊あたり2スロット程度消費する。それとは別にダウンロードコインというのが月5枚提供されて、これを使ってダウンロードが出来てオフラインで読める。5枚使っちゃったらコインだけ買うことも出来て5枚で$10。ただこれはかなり高い感じで、10ページ程度で1コイン使う感じになる。全部ダウンロードするのではなく、オンラインで立ち読み(?)して、一部だけ欲しかったらここでダウンロード、全部欲しかったら別のサイトでpdf版を買った方がいい感じだ。
このSafari Bookshelfって色んな本屋でやっているようで、手続きした後、飯食ってから「どこだっけ?」といいかげんにグーグルさんに聞きながら行ったら、別の本屋のSafari Bookshelfに行ってしまいパスワードが違うといわれて焦ってしまった。なんかアメリカのオンライン書店はどんどん進んでいくね。
Java Generics and Collections
ちょっと時間があったので、とりあえず第一部を読んでみた。う〜む、落とし穴いっぱいだ。やはり配列がreifiableなのに対し、GenericsはErasureベースでreifiableでないところが一番大きいのかな。とはいえC#みたいに実行時型情報を持つと、既存コードとの互換性が、かなり犠牲になりそうなので、過去の資産を大量に抱えるJavaにとっては現実的な解なんだろう。
reifiableって何と訳すんだろう「具象化可能」とかかな。しかし日本語でも意味不明だな。「型パラメータに関する実行時型情報を持つ」の方が意訳ではあるけど分かりやすい気がする。
第二部は、単なるコレクションフレームワークの説明だし、第一部もGenericsに関係無い機能の説明もあるから、実質はページ数で半分くらいかも。しかし、第二部はコレクションフレームワークの説明としては、これまで全く見たこと無いくらい秀逸な解説だ。初めてコレクションフレームワークを勉強する人にもお勧め。
電池購入
T30の頃に比べたらはるかにマシになったとはいえ、この前病院で使っていたらやはり2時間しかもたなかった。もう二年近く経つしなぁ。
とりあえずT60もウルトラスリムベイのようなので、社員販売(なぜか、まだ社員販売なのだな)で、バッテリを購入。
Collections.unmodifiableIterable()が欲しい。
何で無いのかな〜。既存のIterableを変更不可のIterableにwrapする。こんな感じか。
public final class UnmodifiableIterable<E> implements Iterable<E> {
Iterable<? extends E> itr;
public UnmodifiableIterable(Iterable<? extends E> itr) {
if (itr == null) throw new NullPointerException();
this.itr = itr;
}
public Iterator<E> iterator() {
return new Iterator<E>() {
Iterator<? extends E> z = itr.iterator();
public boolean hasNext() {
return z.hasNext();
}
public E next() {
return z.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
サンサーンス「オルガン付き」
サントリーホールに行く度に、あのパイプオルガンを聞いてみたいものだなと思っていたので、今日はサンサーンスのオルガン付き。やっぱりこれは生で聴かないと。超低音の地響きと空気の震えはオーディオセットでは体感できない感覚だ。なぜかプログラムは新世界とセットになっていた。どうもこの曲は苦手だ、というかドボルザークの長い曲は苦手。特にこの曲はバタくさいメロディが、楽章を超えてまで、これでもかと繰り返されて、げんなりしてしまう。幸い新世界の方が先だったので救われた。けどアンコールがハンガリー舞曲で、よみがえってきてしまったよ。
席が前過ぎたのでサンサーンスは、もう一度二階席で聴いてみたい。
Windowsとロケール
最近、仕事の関係でロケールを英語に切り替えて使う事が多い。で、そうやって使うと、色々と妙な事が起きることが分かった。日本語Windows入れていながら英語のロケールで使うなんてケースは、ほとんどないだろうから、あまりデバッグされていないのだろう。
まず、ロケールにかかわらず、突然キーボード配列が英語キーボードになる事がある。そういう時は、落ち着いてタスクバーを出してみると"EN"というアイコンが表示されている。

これをクリックして日本語に切り替えれば正常になる。ただ、なぜかタスクバーをセカンドディスプレイ側に持っていっていると、クリックしたとたんにアイコンが消えて、何もできなくなる。一旦プライマリ側にタスクバーを持っていけばいいのだけど、面倒な事この上ない。
入力ロケールが切り替わってしまうのは、多分切り替えのキーシーケンスを押してしまっているためだと思われるのだが、

このチェックボックスを外してやっても、しばらくすると知らない内にチェックが入っていて元の木阿弥だ。英語版Windowsを日本語ロケールで使った方が快適だったりするのだろうか。
最近のPCの電源スイッチ
昔はPCの電源スイッチは、機械式で〇、│と表記されていた。これはパイプの中に置く円盤状の流量調整弁が由来で、〇だと塞ぐからoff、│だとonになるというのを大学に入ってから初めて聞いた。が、ちょっと探してみた感じでは由来についてちゃんと説明しているページは見つからなかった。でも多分正しいのだろう。他に二進法の0と1とかIn/Outという説があるようだけど、自分が大学の頃の教授(しかも化学科)の世代ではコンピュータなんて全く一般的ではなかったはずで、二進法が入り込む余地があったとは思えないし、別にコンピュータに限らず普通のスイッチでも使われている。In/Outって英語としては変な気がする。InはまだしもOutって...普通はturn on/offだろうし。
で、いつ頃からかPCのスイッチは単なる押しボタンになって、そこには〇の上に│が突き刺さったマークに変わった。これって〇と│を兼ねているからだろうと理解していたのだけど、ここを見ると分かるようにスタンバイの意味だったのだ。このボタンって電源じゃなくて、スタンバイスイッチだったのだね。電源ボタンの機能はWindowsならコントロールパネルで設定できて、デフォルトは電源off/onだけど、本当はスタンバイをデフォルトにしたかったんじゃないだろうか。でもハードウェアの相性とかでなかなかスタンバイが安定運用できるケースが少ないので仕方なく電源off/onになってるとか。
本日のハマリ:BigDecimal使ったのに誤差が出る
「計算結果に誤差が出ます」
「浮動小数点数を使っているのでは?」
「ちゃんとBigDecimalを使ってます」
public class Test {
private static final BigDecimal MAX_TOTAL = new BigDecimal(10000000000000001L);
public static void main(String[] args) throws Exception {
System.out.println("Value = " + MAX_TOTAL.longValue());
}
}
J2SE1.4までだとBigDecimal(long)というのは無いから、doubleに昇格されて、BigDecimal(double)が呼び出される。しかしdoubleの仮数部は53bitしかないから、この引数だと誤差が発生する。1.4迄だと結果は
Value = 10000000000000000
同じソースをJ2SE5.0でコンパイルし直した場合、BigDecimal(long)が使用されるので、誤差が発生しない。
Value = 10000000000000001
1.4までの場合は文字列バージョンを使用しないといけない。
private static final BigDecimal MAX_TOTAL = new BigDecimal("10000000000000001");
多分「53bitで表現できる範囲をこえるなら文字列で」なんて難しいコーディングルールを作っても、遵守は困難だろうから、常に文字列版を使用させるのが無難かな。チェックはBigDecimal(double)の呼び出しを見つけるディテクタ作ってFindBugsで見つけるのが簡単そう。
液晶の位置を移動
机上での猫の領域拡大を阻止するため、仕方なく猫ベッドが置いてあるのだが、スペースが十分でなく1/3くらいはみ出していた。このため眠りこけた卯之吉がベッドごと転落して、お尻からボテっと落ちるという痛ましい事故が相次いだため、液晶の位置を変更。今まではメインディスプレイの右にセカンダリを置いてあったのだけれど、これを左側に移動してスペースを空けた。どうもセカンダリ側にスタートメニューを探しに行ってしまうので、スタートメニューをセカンダリ側に移動してみた。
カフェポッド
エスプレッソが好きなのだけど、そんなに量は飲まないので、普通の粉を買うとすぐダメにしてしまう。そこでポッドというのを愛用している。これは1回分ずつが個別包装になっているので、長期間保存できるのだ。今まではヤマギワリビナで、このポッドを買っていたのだけど、最近ひいきにしていた銘柄(HAUSBRANDT)の取り扱いが終わってしまった。インターネット上を探してみたが、どうもほとんど見つからない。もしかしてHAUSBRANDT自体が販売をやめちゃったのかな。とりあえずここで6種類の詰め合わせセットを頼んでみた。気に入ったのが見つかればいいのだけど。
EclipseでJUnit実行時に-eaしたい。
やっぱり全然使えないのもまずいという事で、Eclipseを頑張って使おうとしているのだけど、なかなか思った通りに行かない。今日はJUnit実行時に-ea指定する方法を探してみたけど、結局見つけられなかった...Windows->Preferencesとプロジェクト->Preferencesの他に、どの辺に設定があるのだろうか。
中が見えるHDD
思いっきりニッチだと思うんだけど、良く作ったなぁ。自作向けを見込んでいるんだろうけど、意外とメーカ製でもわざわざ外からHDDが見えるPCとか出すかもしれないな。何がウケるか分からないし。しかしATAも10000回転の時代か。
J2SE 1.4で、5.0のコードを動かす。
前にjsr14オプションの事を書いたけど、同様な事をAOPで実現するretroweaverをちょっと試してみた。
import java.util.*;
public class Test {
enum Cats {RUIMO, UNOKICHI}
public static void main(String[] args) {
List<String> list = new ArrayList();
list.add(Cats.RUIMO.toString());
list.add(Cats.UNOKICHI.toString());
for (String name:list) {
System.out.println(name);
}
}
}
もちろん1.4では動かない。
$ d:/j2sdk1.4.2_08/bin/java -cp "retroweaver-rt.jar;." Test
Exception in thread "main" java.lang.UnsupportedClassVersionError: Test (Unsuppo
rted major.minor version 49.0)
at java.lang.ClassLoader.defineClass0(Native Method)
...
retroweaverをダウンロード、jarを解凍して、releaseの下にある実行可能jarであるretroweaver-ex.jarを起動。

Source:にクラスファイルを置いたディレクトリを指定して、Version:にターゲットバージョンを指定(1.3とか1.2とかもあるけど、retroweaverのランタイムが1.4でコンパイルされているので動かなかった)。
$ d:/j2sdk1.4.2_08/bin/java -cp "retroweaver-rt.jar;." Test RUIMO UNOKICHI
おぉ、動く。enumも使えるじゃん。既存クラスの中に5.0からバラバラに追加されたメソッドはどうかな。
public class Foo {
public static void main(String[] args) {
Integer i = Integer.valueOf(0);
}
}
これも問題なく実行できた。weave後のバイトコードを見てみると、
public static void main(java.lang.String[]); Code: Stack=1, Locals=2, Args_size=1 0: iconst_0 1: invokestatic #26; //Method com/rc/retroweaver/runtime/Autobox.valueOf :(I)Ljava/lang/Integer; 4: astore_1 5: return
なるほどretroweaverのランタイム内のクラスを使用するように書き換えられているようだ。じゃprintfなんかも使えちゃうのか?
public class Bar {
public static void main(String[] args) {
System.out.printf("Hello %s%n", "World");
}
}
残念、これはだめだった。
$ d:/j2sdk1.4.2_08/bin/java -cp "retroweaver-rt.jar;." Bar
Exception in thread "main" java.lang.NoSuchMethodError: java.io.PrintStream.prin
tf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
at Bar.main(Bar.java:3)
まだ全部の5.0追加機能はサポートされていないようだ。なかなか面白い。でも仕事で使うのはちょっとリスキーかな。NoSuchMethodError爆弾を抱える事になるしね。
W-ZERO3
W-ZERO3レビュー。うまくまとめてるな〜。自分的にはLinux Zaurus(SL-C750)使い続けるつもり。Two Linkなら64kbpsだけど月額基本料が1k円で済むし、自宅にISDNルータを置いておけばプロバイダも不要だし。しかしARMはなかなかスピードが上がりませんな。やっぱり数が出なくて投資できないのかなぁ。
Genericsむずい
Generics、やっぱり難しいな〜。Java Generics and Collectionsって、内容的にはここにあるpdfと比べて、どのくらい加筆されてるんだろう。買ってもしょうがないかな〜。とはいえこれより詳しい本って無さそうだし。この値段なら買っておくしかないか。ってまだ出てませんな。
1対多の関係を作ろうとして
class Child {
}
class Parent<CHILD_T extends Child> {
Collection<CHILD_T> children;
Iterator<CHILD_T> iterator() {
return children.iterator();
}
}
まぁ、この辺まではいい。で、子から親にもリンクを張ろうとして、
class Child<PARENT_T extends Parent> {
PARENT_T parent;
PARENT_T getParent() {
return parent;
}
}
この辺から怪しい。Childに型パラメータが付いたわけだから、Parent側の
Parent<CHILD_T extends Child>
のChildに型パラメータが付いていないってことは、Objectなわけで、
Parent<CHILD_T extends Child<Object>>
ってことになる(はず。自信なし)。それが証拠に、
class Child<PARENT_T extends Parent> {
PARENT_T parent;
PARENT_T getParent() {
return parent;
}
void bar() {
parent.foo(this);
}
}
class Parent<CHILD_T extends Child> {
Collection<CHILD_T> children;
Iterator<CHILD_T> iterator() {
return children.iterator();
}
void foo(CHILD_T child) {
}
}
$ javac -Xlint:unchecked Child.java Parent.java
Child.java:10: 警告: [unchecked] raw 型 Parent のメンバとしての foo(CHILD_T) へ
の無検査呼び出しです。
parent.foo(this);
^
警告 1 個
やっぱりね〜。ってことはえ〜と、
class Parent<CHILD_T extends Child<? extends Parent<CHILD_T>>> {
class Child<PARENT_T extends Parent<? extends Child<PARENT_T>>> {
ですか? もうわけわからなくなってる。
$ javac -Xlint:unchecked Child.java Parent.java
Child.java:10: foo(? extends Child<PARENT_T>) (Parent<? extends Child<PARENT_T>>
内) を (Child<PARENT_T>) に適用できません
parent.foo(this);
^
エラー 1 個
Child<PARENT_T>の継承型を受け取れるメソッドに、どうしてChild<PARENT_T>が渡せないですか? もう理解不能。もう一度pdfを熟読してみよう...
ホワイトボード
ホワイトボードを買った。UMLを貼り付けておく場所が欲しいのと、ちょっとしたメモを紙に書いては捨てるのがもったいないので。
なかなか便利で良い感じ。しかし机の半分くらいを猫に占領されるのは何とかならないものか。

設計の不備でも指摘してくれればなぁ。
スクロール(2)
全く別にJScrollBarをnewしておいて、JScrollPane.setHorizontalScrollBar()で設定してみたが、スクロールバーの場所はJScrollPane側で決められてしまうようで、外観上は何も変わらない感じ。

何となく旨くいっている感じ。こんなことしていいんだろうか。もっとまともなやり方はないものか。
スクロール
こんなUIを作りたくて、試行錯誤中。

縦にSplit paneで分かれた領域があって、個々の領域には縦のスクロールバーが、そして、全体に1つの横のスクロールバー。

これだと、

水平にスクロールすると、垂直スクロールバーが隠れてしまうし、一番下の領域が外に溢れて垂直スクロールバーが出ない。












