Java 为什么在这里工作而在这里不工作?

Java 为什么在这里工作而在这里不工作?,java,Java,为什么第8行可以工作,即使“out”引用为null,而在第9行,我做了另一个与引用“out”相同的引用(类型为“PrintStream”的静态final,值为null)不能工作,我得到了“NullPointerException”?系统。out有点神奇。尽管它是final并用null初始化,但它实际上具有非null值 之所以发生这种情况,是因为JVM对该字段(以及其他一些字段)进行了特殊处理 你不能用纯java复制这种行为,你需要使用不安全的魔法。我认为你的第二张图片显示的是java.lang.


为什么第8行可以工作,即使“out”引用为null,而在第9行,我做了另一个与引用“out”相同的引用(类型为“PrintStream”的静态final,值为null)不能工作,我得到了“NullPointerException”?

系统。out
有点神奇。尽管它是
final
并用
null
初始化,但它实际上具有非null值

之所以发生这种情况,是因为
JVM
对该字段(以及其他一些字段)进行了特殊处理


你不能用纯java复制这种行为,你需要使用不安全的魔法。

我认为你的第二张图片显示的是
java.lang.System
的代码片段

我想你是在问“为什么
System.out.println
System.out
final
并初始化为
null
的情况下仍然有效?”

答案是<强大>魔法

JVM初始化中有一些深层次的魔法,将非空值重新分配给
System.in
System.out
System.err
。事实上,Java语言规范中甚至提到了这些字段的特殊性(如果您好奇的话)

类似的魔法也被用来使
系统。出发(…)
和朋友们工作

依我看,最好是相信它是有效的。。。不要问怎么做


由此推论,您尝试执行类似操作失败的原因是
x
字段的行为符合预期。它已初始化为
null
,并保持这种状态。这里没有魔法。你的代码不是“特殊的”


(值得一提的是,在某些情况下,可以使用反射来修改
final
字段的值。但这不是一个好主意。首先,JLS没有仔细说明执行此操作时会发生什么;请参见。)

请将代码作为文本发布在此处。这不是典型的NPE问题。请相信我……@luk2302这是
final
字段,因此有理由认为该值不会改变。在本例中,它发生了变化,但这只是因为
JVM
magic这样您就可以看到System.out不是空的,但是当您进行调用时,x是空的。
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");

   }
}