Using reflection and also from the src.zip available in the installed JDK by the installer purveyed by http://docs.oracle.com, I found the following fields of java.lang.System,
in, out & err are declared as final, but they have respective (public) setter methods which in turn invoke their respective native couter-part.
For example, I could successfully re-direct console output to a file.
We can set final variables exactly once we have initialized it in the Java code.
My question is : is this rule of final not applicable to the native code?
Native code can break the rules on
final. It can also break the access rules and basic type safety, and various other things.The point about
finalfields not actually being immutable is actually recognized in the JLS: see JLS 17.5.3. The gist of this is that if you do change afinal(via reflection for example), certain guarantees no longer hold. And changing the value of afinalthat represents a compile time constant is liable to have no effect at all.But as @ignis points out,
System.in/out/errget special mention in the JLS as being “write-protected” (JLS 17.5.4) rather than having the normalfinalsemantics. Basically, this means that thefinalguarantees do hold even if the variables are changed.In this particular case it is 1) to prevent
System.in/out/errfrom being clobbered by an accidental assignment, and 2) so that changes can be controlled by theSecurityManager.