【问题标题】:System.out is declared as static final and initialized with null? [duplicate]System.out 被声明为 static final 并初始化为 null? [复制]
【发布时间】:2015-10-22 23:46:24
【问题描述】:

当我浏览System.class 时,我发现了一些对我来说似乎很奇怪的东西。当您查看System.in, System.out, System.err 的声明时,这些声明被标记为final static,但也使用null 进行了初始化

public final static InputStream in = null;  
public final static PrintStream out = null;  
public final static PrintStream err = null;

既然final 只能初始化一次,那么这些是如何管理的呢?
当我们使用System.out.print("..."); 时,很明显out 不是null 而是final static 怎么不是null

那么谁能解释一下已经声明为 final 的 out 是如何初始化的?

【问题讨论】:

    标签: java reflection stream


    【解决方案1】:

    它在静态初始化程序中使用本机代码进行初始化。 在 System.java 的顶部,您有:

    /* register the natives via the static initializer.
     *
     * VM will invoke the initializeSystemClass method to complete
     * the initialization for this class separated from clinit.
     * Note that to use properties set by the VM, see the constraints
     * described in the initializeSystemClass method.
     */
    private static native void registerNatives();
    static {
        registerNatives();
    }
    

    registerNatives() 方法将初始化 in/out/err - 它在本机代码中这样做 - 本机代码几乎可以为所欲为,并且不限于所有 Java 语言规则。 (虽然你也可以通过反射在 Java 中设置一个已经初始化的 final 字段)

    【讨论】:

      【解决方案2】:

      既然 final 只能初始化一次,那么这些是如何管理的呢?

      虽然您可以通过反射更改 static final 变量,但在这种情况下,字段是通过本机方法更改的。

      来自 java.lang.System

      public static void setIn(InputStream in) {
          checkIO();
          setIn0(in);
      }
      
      // same for setOut(), setErr()
      
      private static native void setIn0(InputStream in);
      private static native void setOut0(PrintStream out);
      private static native void setErr0(PrintStream err);
      

      当我们使用 System.out.print("...");很明显 out 不是 null 而是一个 final static 它怎么不是 null ?

      在你有机会使用它之前就设置好了。

      您可能想知道为什么会这样?答案几乎可以肯定与加载类的顺序有关。许多类按顺序启动,但它们需要按有效的顺序进行初始化。

      那么谁能解释一下已经声明为 final 的 out 是如何初始化的?

      这是因为final 并不像您想象的那么最终。有人建议我们需要final final

      【讨论】:

      • 我真的不明白为什么使用public 访问器方法使in 成为private,非final 字段不是更好的选择。那么根本就不需要本地方法。我错过了什么吗?
      • @pbabcdefp System.in 是在二十年前 Java 1.0 发布之前添加的。这是您现在最有可能采取不同做法的事情之一。
      猜你喜欢
      • 2014-03-09
      • 2013-06-12
      • 2011-10-02
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      • 2013-07-07
      • 1970-01-01
      • 2018-06-13
      相关资源
      最近更新 更多