为什么java中system.out.println(),不会报空指针异常...

源文件中,其中“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只是让用户无法赋值而已。

 
 
posted @   四叶草的诗雨  阅读(403)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
这是lious的博客,欢迎阅读「 为什么java中system.out.println(),不会报空指针异常... 」
点击右上角即可分享
微信分享提示