Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java System.out声明为静态final,并用null初始化?_Java_Reflection_Stream - Fatal编程技术网

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发布之前添加的。这是你现在最有可能改变的事情之一。