1
0

More than 1 year has passed since last update.

Systemクラスのクラス変数について

Last updated at Posted at 2022-03-05

Systemクラスのクラス変数について

〜JavaAPIを読んで見るシリーズ〜 個人メモ用
以外に奥が深かったよSystem.out.printlnの巻

Systemクラスにて宣言されているクラス変数について、色々わからなかったので調べてみました。

System.java
public final static InputStream in = null;
public final static PrintStream out = null;
public final static PrintStream err = null;

【疑問点1】
・System.out.println の変数 out には null が入っているはずなのに
 なぜprintlnメソッドを呼び出せるのか
・変数outはfinal修飾子であり、nullで初期化しているのであとから変数を
 代入することは不可能なはず?

■final修飾子にあとから値を代入する例

TEST1_final.java
public class TEST1_final {
    public final static String value1 = null;

    public static void main(String[] args) {
        value1 = "aaa";
        System.out.println(value1);
        }
}

■実行結果

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	final フィールド TEST1_final.value1 には代入できません

	at javaAPI_練習用/TEST1.TEST1_final.main(TEST1_final.java:6)

やはりエラーでした。

というか、System.inとかSystem.outを出力したら変数の中身ある…

public class TEST1 {
    public static void main(String[] args) {
        System.out.println(System.in);
        System.out.println(System.out);
        System.out.println(System.err);
    }
}

■実行結果

java.io.BufferedInputStream@448139f0
java.io.PrintStream@7cca494b
java.io.PrintStream@7ba4f24f

いつ誰が代入したの…

【調べた結果まとめ】
同Systemクラス内にinitializeSystemClassというメソッドがあります。
このメソッド内にて値を設定しています。
ちなみに、このメソッドはJVM初期化時に動いているらしいです。

System.java
    private static void initializeSystemClass() {
        
        (省略)
        
        setIn0(new BufferedInputStream(fdIn));
        setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
        setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));

■定義元(同Systemクラス内)

    private static native void setIn0(InputStream in);
    private static native void setOut0(PrintStream out);
    private static native void setErr0(PrintStream err);
native修飾子がついているのでこのメソッドは別言語で実装されていてそこで値を設定している。)

【疑問への回答】
・Systemクラスの各final変数は同クラス内のinitializeSystemClassメソッドを使って値を代入している。
・低レイヤーな他言語(多分Cとか)で代入している。
・initializeSystemClassはJVMの初期化辺りのタイミングで呼ばれる。
※呼ばれるタイミングについては理解がまだ曖昧です。。調べるの時間かかりそうなので後回し

以上

【参考】
https://stackoverflow.com/questions/19173965/why-are-the-printstream-out-and-inputstream-in-null
https://ytetsuwo.hatenadiary.org/entry/20110816

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0