System.out声明为static final并用null初始化?

时间:2015-07-31 10:17:53

标签: java reflection stream

当我经历new A();时,我发现了一些对我来说很奇怪的东西。当您查看System.class的声明时,这些声明会被标记为System.in, System.out, System.err,但也会使用final static初始化

null

由于public final static InputStream in = null; public final static PrintStream out = null; public final static PrintStream err = null; 只能初始化一次,然后如何管理它们? 当我们使用final很明显System.out.print("...");不是out而是null它不是final static

那么任何人都可以解释如何初始化已经宣布为最终的?

2 个答案:

答案 0 :(得分:8)

在静态初始化程序中使用本机代码初始化它。 在System.java的顶部,你有:

/* register the natives via the static initializer.
 *
 * VM will invoke the initializeSystemClass method to complete
 * the initialization for this class separated from clinit.
 * Note that to use properties set by the VM, see the constraints
 * described in the initializeSystemClass method.
 */
private static native void registerNatives();
static {
    registerNatives();
}

registerNatives()方法将初始化in / out / err - 并且它在本机代码中执行 - 本机代码几乎可以做任何想做的事情,并且不限于所有java语言规则。 (虽然你也可以通过反射在Java中设置已初始化的最终字段)

答案 1 :(得分:5)

  

因为final只能初始化一次然后如何管理它们?

虽然您可以通过反射更改static final变量,但在这种情况下,字段会通过本机方法更改。

来自java.lang.System

public static void setIn(InputStream in) {
    checkIO();
    setIn0(in);
}

// same for setOut(), setErr()

private static native void setIn0(InputStream in);
private static native void setOut0(PrintStream out);
private static native void setErr0(PrintStream err);
  

当我们使用System.out.print(“...”)时;很明显out不是null,而是最终的静态如何不为null?

在您有机会使用它之前设置它。

您可能想知道为什么会这样做?答案几乎肯定与加载的订单类有关。许多类按顺序启动,但需要按照有效的顺序进行初始化。

  

那么任何人都可以解释如何初始化已经宣布为最终的?

这是因为final并不像你想象的那样最终。有人建议我们需要final final