System.out.println() 解題Revised: Jan./8th/2001
単純なスタンドアロンアプリケーションでは、標準出力への出力は次のように書く:
//行末で改行なし System.out.print(); //行末で改行付き System.out.println();
これは任意のクラスで自由に使える。何故だろうか? System.out は System クラスのメンバ変数呼び出しであり、 print() メソッドは PrintStream クラスである。そんなことが許される理由は何だろうか?
SystemSystem クラスは java.lang パッケージに含まれる。全てのクラスでは java.lang パッケージは自動的にインポートされている。したがって、 public 宣言が付いた System クラスは自由に使える。
但し、 System クラスはインスタンス化できない。System.java のソースコードを確認すると、コンストラクタが private 宣言されていた。
System クラスはどこからでも参照できるが、インスタンス化は出来ないようになっている。
outout は System クラスで定義されたメンバ変数(フィールド)であり、既に開いている標準出力ストリームを意味する。修飾子は public final static PrintStream であり、 static 宣言されているので、 System クラスをインスタンス化しなくとも、クラス名で直接アクセスできる。
また、この変数の型は PrintStream クラス型である。このクラスは java.io パッケージに含まれるが、 System クラスでは冒頭でこのクラスをインポートしているので、この使用法に関して問題はない。
この変数は、既に開いている標準出力ストリームをオブジェクトとして参照する。この使用法が変更されないように、 final 宣言がされており、事実上のパラメータとなっている。
print(), println()これらのメソッドは PrintStream クラスで定義されているので、 PrintStream 型で定義されている変数 out をオブジェクトとしたメソッドになれる。
オブジェクトを明示する為に、参照型変数の代入をしてみよう。ここでは、 PrintStream 型の変数 out を、別の PrintStream 型の変数に代入している。System クラスのメンバ変数として定義されている out は、任意のクラスから System.out で参照できる:
PrintStream obj = System.out; obj.println();
PrintStream 型変数である obj に対して、参照のコピーが行われている。参照先は Syste.out 、すなわち標準出力ストリームである。この標準出力ストリーム・オブジェクトのメソッド println() を呼び出しているわけである。
ここでは、オブジェクトを明示する為に新たに変数を定義して代入したが、直接メソッド呼び出しすれば、次のようになるわけだ:
System.out.println();
実際には、 System.in, System.out を標準入出力デバイスに関連付けるために、システムのネイティブな函数を利用している。順番としては、空の入出力ストリーム System.in, System.out を定義し、これをネイティブメソッドの中で PrintStream 型の標準入出力ストリームと関連付けている。標準入出力を要求すると、 Java VM はネイティブな函数 (DLL: Dynamic Link Library) を通して、OSのカーネルへ対応するデバイスの制御を受け渡しているわけだ。