当我经历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
?
那么任何人都可以解释如何初始化已经宣布为最终的?
答案 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
。