源文件中,其中“out“是public static final printstream out = null”
貌似我们学过变量一旦被final修饰,其值不可改变
源码的解释:
final修饰的PrintWriter类引用out无法在Java语言层面改变值,但使用JNI进行系统调用重定向打印流对象。 /*initalizeSystemClass中调用了setIn0、setOut0和setErr0方法,猜想这是在设置System.in、System.out和System.err流对象。setOut0被声明为了一个native(本地)方法,需要用到JNI,因而看不到setOut0方法的实现。*/ private static native void setOut0(PrintStream out); // 但有一个相似的setOut方法。 /** * Reassigns the "standard" output stream. * ... * @param out the new standard output stream * ... */ public static void setOut(PrintStream out) { checkIO(); setOut0(out); } //注释中指出,通过setOut方法重赋值标准输出流。可以推测,out对象是通过JNI赋的值~
源码部分:
/** * The following two methods exist because in, out, and err must be * initialized to null. The compiler, however, cannot be permitted to * inline access to them, since they are later set to more sensible values * by initializeSystemClass(). */ private static InputStream nullInputStream() throws NullPointerException { if (currentTimeMillis() > 0) { return null; } throw new NullPointerException(); } private static PrintStream nullPrintStream() throws NullPointerException { if (currentTimeMillis() > 0) { return null; } throw new NullPointerException(); } 注意这个的注释,这段注释中提到了一个方法 initalizeSystemClass,上面说到的setOut方法就是在这个方法里被被调用的,这个方法的注释: /** * Initialize the system class. Called after thread initialization. */
System.out
这个值其实可以由System.setOut()
这个方法来设定的,它其实是个native
的方法。Java代码前面加了
final
只是让用户无法赋值而已。