public class Main {
public static final PrintStream x = null;
public static void main(String[] args) {
/*Line 8*/ System.out.println("Da");
/*Line 9*/ x.println("Da");
}
}
即使“ out”引用为空,第8行为什么也能正常工作,在第9行,我与引用“ out”进行了相同的引用(类型为“ PrintStream”的静态最终值,值为null),为什么无法正常工作,我收到“ NullPointerException”?
答案 0 :(得分:5)
我认为您的第二张图片显示了java.lang.System
的代码段。
我想您是在问“尽管System.out.println
被System.out
并初始化为final
,null
的工作原理”。
答案是... 魔术!
JVM初始化中存在一些深层的黑魔法,可将非空值重新分配给System.in
,System.out
和System.err
。确实,这些字段的特殊性甚至在Java语言规范中都有提及(17.5.4,如果您感到好奇的话)。
类似的魔法用于使System.setOut(...)
和朋友工作。
IMO,最好只是相信它能起作用...而不要问如何做。
推论是,您尝试执行类似操作无效的原因是您的x
字段的行为符合预期。它已被初始化为null
,并保持这种状态。这里没有魔术。您的代码不是“特殊”代码。
(对于有价值的东西,在某些情况下可以使用反射来修改final
字段的值。但这是个坏主意。首先,JLS并未仔细指定这样做时会发生;请参见17.5.3。)
答案 1 :(得分:4)
System.out
有点神奇。尽管它是final
并用null
初始化的,但实际上它具有非null值。
发生这种情况是因为JVM
对那个(和其他)字段有特殊的对待。
您不能使用纯Java来重现这种行为,需要使用不安全的魔术。