下面是来自java.lang.System类的代码(JDK1.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呢?
无论如何,将通过System类中的以下setOut方法设置out
public static void setOut(PrintStream out) {
checkIO();
setOut0(out);
}为什么JLS需要nullPrintStream方法?
发布于 2013-03-22 16:46:33
看看private static void initializeSystemClass() -这个方法被调用来启动程序,它调用setOut0(),这是一个native方法。这将Stream绑定到它应该在的位置。
因此,即使字段看起来像public static final,但实际上不是,native代码会更改它。
编辑
OP问为什么JLS需要nullPrintStream方法?
这与java编译器有关-如果static final字段在编译时被赋值为某个常量,比如null,它将“内联”这些字段。编译器实际上会将字段的每个引用替换为常量。
这将破坏初始化,因为对象将不再持有对Stream的引用,而是持有对null的引用。将流分配给方法的返回值可以防止内联。
有些人可能会称它为肮脏的黑客。错误的引用“JDK就像香肠,最好不要看到它被制造出来”。
发布于 2013-03-22 16:42:53
这就是System.out类的初始化方式。
还有一种方法:
private static native void setOut0(PrintStream out);在下面的方法中调用:
private static void initializeSystemClass() {发布于 2013-03-22 16:47:47
System.in、out和err由JVM从本机代码管理。nullPrintStream()的整个魔力就是为了防止javac内联这些字段。从java 7开始,它看起来就像
public final static PrintStream out = null;https://stackoverflow.com/questions/15565993
复制相似问题