java中被final修饰的属性是无法改变的?

本文深入探讨了Java中final关键字的使用,特别是在System类的out属性上下文中。尽管out被声明为final,但通过native方法setOut0(),其值实际上可以被修改。这展示了Java原生方法如何绕过常规的访问控制机制。同时,源码还揭示了System类中对标准输入和错误流的类似处理。这些细节对于理解Java底层工作原理和权限管理至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中是不可变的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值