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

时间:2020-10-02 07:33:38

标签: java

enter image description here

enter image description here

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”?

2 个答案:

答案 0 :(得分:5)

我认为您的第二张图片显示了java.lang.System的代码段。

我想您是在问“尽管System.out.printlnSystem.out并初始化为finalnull的工作原理”。

答案是... 魔术!

JVM初始化中存在一些深层的黑魔法,可将非空值重新分配给System.inSystem.outSystem.err。确实,这些字段的特殊性甚至在Java语言规范中都有提及(17.5.4,如果您感到好奇的话)。

类似的魔法用于使System.setOut(...)和朋友工作。

IMO,最好只是相信它能起作用...而不要问如何做。


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

(对于有价值的东西,在某些情况下可以使用反射来修改final字段的值。但这是个坏主意。首先,JLS并未仔细指定这样做时会发生;请参见17.5.3。)

答案 1 :(得分:4)

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

发生这种情况是因为JVM对那个(和其他)字段有特殊的对待。

您不能使用纯Java来重现这种行为,需要使用不安全的魔术。