java: "final"System.out、System.in 和 System.err?

标签 java final

System.out声明为 public static final PrintStream out

但是你可以调用System.setOut()重新分配它。

嗯?如果它是 final,这怎么可能?

(相同点适用于System.inSystem.err)

更重要的是,如果您可以改变 public static final 字段,就 final 给您的保证(如果有的话)而言,这意味着什么? (我从来没有意识到也没有预料到 System.in/out/err 的行为是 final 变量)

最佳答案

JLS 17.5.4 Write Protected Fields :

Normally, final static fields may not be modified. However System.in, System.out, and System.err are final static fields that, for legacy reasons, must be allowed to be changed by the methods System.setIn, System.setOut and System.setErr. We refer to these fields as being write-protected to distinguish them from ordinary final fields.

The compiler needs to treat these fields differently from other final fields. For example, a read of an ordinary final field is "immune" to synchronization: the barrier involved in a lock or volatile read does not have to affect what value is read from a final field. Since the value of write-protected fields may be seen to change, synchronization events should have an effect on them. Therefore, the semantics dictate that these fields be treated as normal fields that cannot be changed by user code, unless that user code is in the System class.

顺便说一句,实际上你可以通过反射来改变 final 字段,方法是调用它们的 setAccessible(true) (或者使用 Unsafe 方法).这种技术在反序列化过程中被 Hibernate 和其他框架等使用,但它们有一个局限性:在修改前看到 final 字段值的代码不能保证在修改后看到新值。所讨论的字段的特别之处在于它们不受此限制,因为它们由编译器以特殊方式处理。

关于java: "final"System.out、System.in 和 System.err?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30061231/

相关文章:

java - 异步任务 ListView

java - 显示数字阶梯金字塔

java - 为什么内部类接受静态最终变量?

java - 初始化最终字段 - Java

java - 如何阅读特定邮件ID的邮件

java - Spring MVC - 如何在下载开始前显示消息

java - 对类加载时未知的常量使用 final 和 static

java - 公共(public)最终字段的序列化

java - Collections.unmodifiableSet() 在 Java 中做了什么?

java - 如何使用 JSoup 从 HTML a 元素中选择具有特定文本的元素