最终字段的setter方法
使用reflection以及http://docs.oracle.com提供的安装程序中安装的JDK中提供的src.zip,我找到了java.lang.System
的以下字段,
in , out & err被宣布为final,但他们有各自的(公共)setter方法,这些方法反过来调用他们各自的本地couter-part。
例如,我可以成功地将控制台输出重定向到文件。
一旦我们在Java代码中初始化了最终变量,我们就可以设置它们。
我的问题是:这个最终规则不适用于本机代码吗?
我的问题是:这个最终规则不适用于本机代码吗?
本机代码可以破坏final
的规则。 它还可以打破访问规则和基本类型安全性以及其他各种事物。
关于final
字段实际上不是不可变的这一点实际上是在JLS中识别的:参见JLS 17.5.3 。 这样做的要点是,如果你确实改变了final
(例如通过反思),某些保证不再成立。 并且更改表示编译时间常量的final
的值可能完全没有效果。
但正如@ignis指出的那样, System.in/out/err
out/err在JLS中被特别提及为“写保护”( JLS 17.5.4 )而不是正常的final
语义。 基本上,这意味着即使变量发生变化, final
保证也会保持不变。
为什么变量最终会有一个setter?
在这种特殊情况下,1)防止System.in/out/err
被意外分配破坏,2)以便SecurityManager
可以控制更改。
final
使Java Compiler确保没有代码尝试更改除初始化之外的字段。 在java.lang.System中它是不同的
public static void setOut(PrintStream out) { checkIO(); setOut0(out); }
private static native void setOut0(PrintStream out);
从javac的角度来看,没有违规行为。
在源代码中,它们不会在setOut()
方法中重新分配例如out
变量
public static void setOut(PrintStream out) { checkIO(); setOut0(out); }
它们将传递的流发送到本机代码,该代码负责将该流设置为当前使用。 因此,最终变量不会被重置,并且此变量不会在本机代码中使用,无论它传递给本机代码的流是什么,它都会使用
- 如何在Android的OpenCV中在Touch上的框架上绘制多个矩形?
- GAE / J:如何将多部分MIME消息从appengine发布到facebook
- Scanner在nextInt上抛出NoSuchElementException
- 显示Android蓝牙设备名称
- JSF2与GAE和ViewScoped ManagedBean
- 在java.util.Scanner.throwFor(未知来源)错误
- 用于创作音乐的Android应用程序:初学者
- android.database.CursorIndexOutOfBoundsException …再一次
- 如果存储在concurrentHashMap中,POJO对象中的可变字段是否安全?