System.out
声明为 public static final PrintStream out
。
但是你可以调用System.setOut()
重新分配它。
嗯?如果它是 final
,这怎么可能?
(相同点适用于System.in
和System.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
, andSystem.err
are final static fields that, for legacy reasons, must be allowed to be changed by the methodsSystem.setIn
,System.setOut
andSystem.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/