java:" final" System.out,System.in和System.err? [英] java: "final" System.out, System.in and System.err?

查看:103
本文介绍了java:" final" System.out,System.in和System.err?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

系统。 out 被声明为 public static final PrintStream out

但是你可以致电 System.setOut() 重新分配。

But you can call System.setOut() to reassign it.

嗯?如果它是 final

(这一点适用于 System.in System.err

更重要的是,如果你可以改变公众静态最终字段,这对于 final 给出的保证(如果有的话)意味着什么? (我从未意识到也没有预料到System.in/out/err表现为最终变量)

And more importantly, if you can mutate the public static final fields, what does this mean as far as the guarantees (if any) that final gives you? (I never realized nor expected System.in/out/err behaved as final variables)

推荐答案

JLS 17.5.4写保护字段


通常,不能修改最终的静态字段。但是 System.in System.out System.err 是最终的静态字段,由于遗留原因,必须允许通过方法 System.setIn System.setOut System.setErr 。我们将这些字段称为写保护,以区别于普通的最终字段。

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.

编译器需要以不同于其他最终字段的方式处理这些字段。例如,读取普通的最终字段对同步免疫:锁定或易失性读取中涉及的屏障不必影响从最终字段读取的值。由于可以看到写保护字段的值发生变化,因此同步事件应该对它们产生影响。因此,语义要求将这些字段视为无法由用户代码更改的普通字段,除非该用户代码位于 System 类中。

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)关于它们(或使用不安全方法)。这些技术在反序列化期间,通过Hibernate和其他框架等使用,但它们有一个限制:在修改之前看到最终字段值的代码不能保证在修改后看到新值。有关字段的特殊之处在于它们不受此限制,因为编译器会以特殊方式处理它们。

By the way, actually you can mutate final fields via reflection by calling setAccessible(true) on them (or by using Unsafe methods). Such techniques are used during deserialization, by Hibernate and other frameworks, etc, but they have one limitation: code that have seen value of final field before modification is not guaranteed to see the new value after modification. What's special about the fields in question is that they are free of this limitation since they are treated in special way by the compiler.

这篇关于java:" final" System.out,System.in和System.err?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆