Java System.out声明为静态final,并用null初始化?
当我在查看Java System.out声明为静态final,并用null初始化?,java,reflection,stream,Java,Reflection,Stream,当我在查看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.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
如何不是null
那么,有人能解释,out是如何初始化的吗?它已经被声明为final了
既然final只能初始化一次,那么如何管理它们呢
虽然您可以通过反射更改静态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呢
在你有机会使用它之前,它就被设置好了
你可能想知道为什么会这样?答案几乎肯定与类的加载顺序有关。许多类都是按顺序启动的,但它们需要按顺序初始化才能正常工作
那么,有人能解释,out是如何初始化的吗?它已经被声明为final了
这是因为final
并不像你想象的那么最终。有人建议我们需要一个final
它是在静态初始值设定项中用本机代码初始化的。
在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中设置一个已经初始化的final字段)我真的不明白为什么在中使用公共访问器方法将设为私有、非final
字段不可取。那么就根本不需要本机方法了。我遗漏了什么吗?@pbabcdefpsystem.in是在二十年前Java 1.0发布之前添加的。这是你现在最有可能改变的事情之一。