J2SE 5.0の可変長引数ってバイトコードどうなってんのかねぇ?とか思いつつ。
http://pcweb.mycom.co.jp/column/java/008/
を読んでたんだけど、でもこの回の解説はあまりにも微妙すぎだった。
printfはjava.lang.System.out.printfだから、まずjava.lang.System.outがなんのクラスであるかを調べる必要がある。java.langはパッケージ、Systemはクラスだ。そうすると、outはSystemのクラス変数、printfはoutクラスのメソッドだということになる。
うーん。outクラスって…どういう説明なんだ。
いいたいことはわからなくもないが誤解を生むんじゃないかなぁ。
後に書いてあるように
ここの「out」はjava.lang.Systemで宣言されているpublicなstaticフィールドであり、
java.io.PrintStreamクラスのオブジェクトへの参照が入っているものである。
だから「System.out」はオブジェクトへを示しておりprintfはそれのメソッド
最後の一文は、
「printfはstaticフィールドoutが指し示すオブジェクトのメソッドだということになる。 」
が正しいはずだ。
java.lang.System.out.printfがわかりにくいなら、java.lang.System.out#printfと表記してもよいだろう。#以降はメソッドであることを意味する。
「クラス名#メソッド名」という書き方は見たことがあるが、
この例に出ているような
「クラス名.フィールド名#メソッド名」
なんていう書き方は見たことがない。余計にわかりにくくしているような気がする。
このコラムはいつもはそこそこおもしろいかと思っていたんだが、
この節の説明は全体的にボロボロである。
次にこう書いてある。
outがどう処理されているかはソースコードを追っていけばわかる。最終的に、java.io.FileDescriptor.outを元に出力ストリームが作成されている。追って読んでいけば、FileDescriptor.outはファイルディスクリプタ1で生成されていることがわかる。
リスト2 FileDescriptor.out - 標準出力のファイルディスクリプタ
public static final FileDescriptor out = new FileDescriptor(1);
ここでもoutが出てくるわけだが、特に初心者は混乱するだろう。
これはFileDescriptor.javaにある記述なので、ここに出てくる
outはFileDescriptorクラスのstaticフィールドであり、
System.outとは何の関係もないわけだがそんな説明は一切なし。
これだけではFileDescriptor.outとSystem.outの間にどういう関係があるのか説明されていない。
それどころか筆者がなぜFileDescriptorクラスを見つけたのかも書かれていない。
「ソースコードを追っていけばわかる」と書かれているのだから
ソースを追っていったのかと思い(JDK1.4.2のコードだけど)追ってみたわけだが…
Systemクラスの方で下記のような記述がある。
private static void initializeSystemClass() { : FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); : setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); :
確かにFileDescriptor.outからStreamを生成している。
それをSystem.outと関連付けるのがsetOut0メソッドのようだ。
setOut0はどういうメソッドなのか。
メソッド名の最後に0が付いていることから推測できる通り…
private static native void setOut0(PrintStream out);
ネイティブメソッドじゃん。
クラスライブラリのソース読んでもわからんやんけ(>_<)
まあ、
「setOut0はどうせSystem.outに引数を代入するのだろう」
という推測はつくし、
「System.outはFileDescriptor.outから作ったPrintStreamである」
という大筋自体は合っているのでこのコラムが全然ダメというわけではないんだけど、
でも局所的に用語がヘンだとか事実とちがうとかがあるので要注意だってことだ。