问题描述
以下是java.lang.System类(JDK 1.6版)的代码
Following is the code from java.lang.System class (JDK version 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
when we write System.out.println("Something");
in our code then why don't we get NullPointerException even when 'out' is set to 'null'
无论如何,out
将通过 System 类中的以下 setOut
方法设置
Anyhow out
will be set via following setOut
method in System class
public static void setOut(PrintStream out) {
checkIO();
setOut0(out);
}
那为什么 JLS 需要 nullPrintStream
方法?
Theyn why JLS needs nullPrintStream
method ?
推荐答案
看看private static void initializeSystemClass()
- 这个方法被调用来启动,它调用setOut0()
这是一个 native
方法.这将 Stream
绑定到它应该在的位置.
Take a look at the private static void initializeSystemClass()
- this method is called to start things up, it calls setOut0()
which is a native
method. This ties the Stream
into where it's supposed to be.
因此,即使该字段看起来 public static final
实际上不是,native
代码会改变它.
So even though the field may look public static final
it actually isn't, the native
code changes it.
编辑
OP 问那为什么 JLS 需要 nullPrintStream 方法?
这与 java 编译器有关 - 如果在编译时将 static final
字段分配给某个常量,例如 null
,它将内联"static final
字段.编译器实际上会用常量替换对该字段的每个引用.
This is to do with the java compiler - it will "inline" static final
fields if they are assigned to something constant at compile time, like null
. The compiler will actually replace each reference to the field with the constant.
这会破坏初始化,因为对象将不再持有对 Stream
的引用,而是对 null
的引用.将流分配给方法的返回可防止内联.
This would break the initialisation as objects would no longer hold a reference to the Stream
but to null
. Assigning the stream to the return of a method prevents the inlining.
有些人可能会称之为肮脏的黑客攻击.错误地引用俾斯麦的话JDK 就像香肠,最好不要看到它被制造出来".
Some might call it a dirty hack. To misquote Bismarck "The JDK is like sausages, it's best not to see it being made".
这篇关于奇怪的“输出"变量,System.out.println()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!