System.setIn()重新分配最终的System.in

时间:2011-08-21 23:48:36

标签: java

  

可能重复:
  java: "final" System.out, System.in and System.err?

虽然我已经多次这样做而没有引起注意,但我刚刚发生这种情况:System.setIn()正在重新分配静态最终System.in

我错过了什么吗?如何重新分配最终字段。

3 个答案:

答案 0 :(得分:7)

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

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

编辑:值得一提的是,您可以“破解”最终字段并通过对它们调用setAccessible(true)(或使用Unsafe方法)来设置其值。这些技术在反序列化期间,通过Hibernate和其他框架等使用,但它们有一个限制:在修改之前看到最终字段值的代码不能保证在修改后看到新值。 3个系统字段有什么特别之处它们没有这个限制,因为 它们被编译器以特殊方式处理

答案 1 :(得分:3)

System.setIn()及其朋友setOut()setErr()都委托给未实施Java访问控制规则的本机方法。

答案 2 :(得分:1)

无论是谁而浪费了JLS部分[1]解释它,都只是愚蠢。

这些字段应该简单地删除final修饰符。它不会破坏二进制兼容性。 [2]

允许用户编写System.out=x不是问题;毕竟他无论如何都可以做System.setOut(x)。编译器需要一个特殊的处理来将第一个赋值转换为第二个方法调用。这比当前的方式更好,它扭曲了 读写语义System.out

如果我们真的不想看System.out=x,请将其设为异常,以便编译器不会编译它。

这两个解决方案是简单的句法内容;没有必要为这个愚蠢的小东西打破Java内存模型。

[1] http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.5.4

[2] http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html#13.4.9