以下是java.lang.System类的代码(JDK版本1.6)

public final static PrintStream out = nullPrintStream(); //out is set to 'null'

private static PrintStream nullPrintStream() throws NullPointerException {
    if (currentTimeMillis() > 0) {
        return null;
    }
    throw new NullPointerException();
}

当我们在代码中编写System.out.println("Something");时,为什么即使'out'设置为'null',我们也为什么不得到NullPointerException

无论如何,out将通过System类中的以下setOut方法设置
public static void setOut(PrintStream out) {
     checkIO();
     setOut0(out);
 }

那么为什么JLS需要nullPrintStream方法?

最佳答案

看一看private static void initializeSystemClass() -调用此方法来启动事情,它调用setOut0(),它是native方法。这将Stream绑定(bind)到了应该的位置。

因此,即使该字段可能看起来像public static final,但实际上看起来不是,但native代码会对其进行更改。

编辑

OP问然后JLS为什么需要nullPrintStream方法?

这与java编译器有关–如果在编译时将它们分配给常量,例如static final,它将“内联” null字段。编译器实际上将用常量替换对字段的每个引用。

这将破坏初始化,因为对象将不再持有对Stream的引用,而是对null的引用。将流分配给方法的返回可防止内联。

有人可能称其为肮脏的骇客。错误地引用Bi斯麦的话:“JDK就像香肠,最好不要看到它在制造”。

09-05 06:26
查看更多