System.out.println("Hello World!");
大家对这个输出语句都很熟悉。
out是System中的一个属性,并且是final修饰的
/**
* The "standard" output stream. This stream is already
* open and ready to accept output data. Typically this stream
* corresponds to display output or another output destination
* specified by the host environment or user.
* <p>
* For simple stand-alone Java applications, a typical way to write
* a line of output data is:
* <blockquote><pre>
* System.out.println(data)
* </pre></blockquote>
* <p>
* See the <code>println</code> methods in class <code>PrintStream</code>.
*
* @see java.io.PrintStream#println()
* @see java.io.PrintStream#println(boolean)
* @see java.io.PrintStream#println(char)
* @see java.io.PrintStream#println(char[])
* @see java.io.PrintStream#println(double)
* @see java.io.PrintStream#println(float)
* @see java.io.PrintStream#println(int)
* @see java.io.PrintStream#println(long)
* @see java.io.PrintStream#println(java.lang.Object)
* @see java.io.PrintStream#println(java.lang.String)
*/
public final static PrintStream out = null;
同时我还发现System中有这样一个修改器方法
/**
* Reassigns the "standard" output stream.
*
* <p>First, if there is a security manager, its <code>checkPermission</code>
* method is called with a <code>RuntimePermission("setIO")</code> permission
* to see if it's ok to reassign the "standard" output stream.
*
* @param out the new standard output stream
*
* @throws SecurityException
* if a security manager exists and its
* <code>checkPermission</code> method doesn't allow
* reassigning of the standard output stream.
*
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*
* @since JDK1.1
*/
public static void setOut(PrintStream out) {
checkIO();
setOut0(out);
}
这个方法的作用从源码的注释开就知道这是修改out属性输出流的一个方法,不是说final修饰的不可变吗?这里就要看看setOut0()这个方法了
private static native void setIn0(InputStream in);
private static native void setOut0(PrintStream out);
private static native void setErr0(PrintStream err);
可以发现不仅仅是 out,就连final修饰的in和err都是可修改的。
在看就会他们同样都被 native 修饰,大家知道native是java中的一个关键字,但是一般很难看到,使用native修饰符修饰的方法表示原生方法,它的实现可能就不是利用java来实现了,所以原生方法可以绕过java语言的访问控制机制。这是一个特殊解决方法。但是我们在编写程序时最好不要模仿这种做法。
综上:用final修饰的字段在java中是不可变的