在方法参数上使用final关键字

经过一些自己的混淆,最终博客方法的具体含义(最终声明的方法参数)将对此博客条目进行澄清。

至少可以将方法参数上的final关键字视为Java编译器的指示符,表明该参数不能重新分配给另一个引用。 Java参数处理始终是“按值调用” (是的,即使在处理对象时也是如此),这是为什么。这是真的。当处理非原始数据类型时,Java处理对对象的引用。 对象本身不会从被调用者传递给目标函数! 而是传递一个指向所需对象的引用。 但是,此引用不等同于被调用方,因为它只是一个副本。 传递给函数的是将复制的引用作为值-好的,每个人都还在吗? :-)也许Java应该使用更匹配的解释“按复制参考调用作为值”

总结一下:

Java仅以“按值调用”样式传递所有方法参数 (原始数据类型或对对象的引用)!

为了证明这一点,让我们看一下下面的演示代码及其输出。

/**
 * Call by Value Test Application.
 *
 * @author Christopher Meyer
 * @version 0.1 
 * Apr 21, 2012
 */
public class CBVTest {

    public static void main(String[] args) {
        Integer mainInternInteger = new Integer(1);

        /*
         * Even references are copied during calls!
         *
         * Explanation Objects are never passed, only references to them, BUT
         * references are copied! So only reference COPIES reach the method.
         * Neither changes to the reference inside/outside the method will
         * influence the counterpart.
         *
         * Maybe it should be called "Call by Copied Reference as Value".
         */

        class RunMe implements Runnable {

            Integer runnerInternInteger;

            public RunMe(Integer i) {
                runnerInternInteger = i;

                /*
                 * The following operation will have no effect on the main
                 * thread, since the reference to "i" is a copied one.
                 * Interfacing the "caller" reference is prevented.
                 */
                i = new Integer(3);
            }

            @Override
            public void run() {
                while (true) {
                    System.out.println(runnerInternInteger.intValue() 
                            + "\t (runner intern value)");
                }
            }
        }

        Thread runner = new Thread(new RunMe(mainInternInteger));
        runner.start();

        // Create a new object and assign it to "mainInternInteger".
        mainInternInteger = new Integer(2);
        while (true) {
            System.out.println(
                    mainInternInteger.intValue() + "\t (main intern value)");
        }
    }
}

代码的输出如下所示:

...
2     (main intern value)
2     (main intern value)
2     (main intern value)
2     (main intern value)
1     (runner intern value)
2     (main intern value)
1     (runner intern value)
2     (main intern value)
1     (runner intern value)
2     (main intern value)
1     (runner intern value)
1     (runner intern value)
1     (runner intern value)
1     (runner intern value)
1     (runner intern value)
 ...

因此,对已处理参数的赋值(i = new Integer(3))或从调用类进行的重新赋值(mainInternInteger = new Integer(2))都不会相互影响。

那么,如果没有必要,那又有什么价值呢?

如果添加到RunMe的构造方法中(公共RunMe(final Integer i)),则重新分配i = new Integer(3)会引发异常:线程“ main”中的异常java.lang.RuntimeException:无法编译的源代码–最终参数我可能不会被分配。 它可以防止因意外重新分配而导致的故障。 意外分配给已处理的参数将始终失败! 最终迫使开发人员生成准确的代码。

final关键字不是方法签名的一部分。 因此,无论是否声明为final,编译后的代码都是相同的(每个人都可以使用diff轻松检查)。 这意味着,一旦声明了方法参数,就不会重载该方法的参数,而一旦声明则不会。 由于字节码保持相同,因此对性能也绝对没有影响。

更令人困惑的是,请记住,在可以修改变量时(例如,在处理线程的匿名内部类时,如果您不清楚在同一上下文中考虑多个变量,则内部类需要定义一个变量final)。可以更改的相同名称)。

参考:Java安全和相关主题博客 ,使用我们JCG合作伙伴 Christopher Meyer的方法参数上的final关键字


翻译自: https://www.javacodegeeks.com/2012/04/using-final-keyword-on-method.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值