方法参数中的final关键字

Aly*_*Aly 146 java final

我经常遇到如下所示的方法:

public void foo(final String a, final int[] b, final Object1 c){
}
Run Code Online (Sandbox Code Playgroud)

如果在不传递最终参数的情况下调用此方法会发生什么.即稍后更改的Object1(因此未声明为final)可以很好地传递给此方法

Thi*_*ler 180

在将参数发送到方法之前,Java总是复制参数.这意味着最终并不意味着调用代码有任何区别.这仅意味着在方法内部无法重新分配变量.(请注意,如果您有最终对象,则仍可以更改对象的属性).

  • 它当然会制作一个副本(有一个优化,编译器不会复制,当制作副本没有区别时).但是,您必须记住,在对象的情况下.该对象实际上只是对对象的引用.因此,在这种情况下,您将获得参考的副本. (68认同)
  • 如果参数的值是参数的源或相同引用的副本,那么这无关紧要.事实上,任何变量只是对内存中实际对象的引用.将参数标记为final将禁止在函数的代码块内重新分配参数.但是,如果参数不是final,尽管可以将参数从传入的参数重新分配给其他任何参数,但函数的调用者永远不会丢失其引用,并继续指向同一个对象. (16认同)
  • 对于未来的读者,请阅读http://javadude.com/articles/passbyvalue.htm而不是这些答案.Java是按值传递的,关键字'final'只关心这个对象不会在方法中意外更改.(或者因为在匿名课程中使用的原因) (12认同)
  • Java仅复制参数的引用,而不复制参数本身。这应该在答案中阐明。 (3认同)

Bal*_*usC 82

在某种情况下,您需要将其声明为final - 否则将导致编译错误 - 即将它们传递到匿名类中.基本示例:

public FileFilter createFileExtensionFilter(final String extension) {
    FileFilter fileFilter = new FileFilter() {
        public boolean accept(File pathname) {
            return pathname.getName().endsWith(extension);
        }
    };

    // What would happen when it's allowed to change extension here?
    // extension = "foo";

    return fileFilter;
}
Run Code Online (Sandbox Code Playgroud)

删除final修饰符会导致编译错误,因为不再保证该值是运行时常量.从匿名类外部更改值将导致匿名类实例在创建之后表现不同.

  • 变量值(声明为final)的变化对内部类有什么影响? (2认同)

Boz*_*zho 52

Java只是按值传递.(或更好 - 按值传递参考)

因此传递的参数和方法中的参数是指向同一对象(值)的两个不同的处理程序.

因此,如果更改对象的状态,它将反映到引用它的每个其他变量.但是,如果为参数重新分配新对象(值),则不会重新分配指向此对象(值)的其他变量.

  • @Aly:不。* reference *是按值传递的,不能在方法中更改-只有它指向的对象才可以更改。 (2认同)
  • 这个答案没有提到"最终关键词"这个话题. (2认同)

Eri*_*rom 32

final方法参数上的关键字对调用者来说绝对没有任何意义.它对运行程序也没有任何意义,因为它的存在或不存在不会改变字节码.它只确保如果在方法中重新分配参数变量,编译器将会抱怨.就这样.但这就够了.

一些程序员(像我一样)认为这是一件非常好的事情并且final几乎用在每个参数上.它使得理解一个冗长或复杂的方法变得更容易(尽管有人可能会认为应该重构长而复杂的方法.)它还会突出显示标记的方法参数final.

  • 我碰巧发现这更像是团队会议。确实没有正确/错误的答案。不过,我有点同意@Erick G. HagstromErick。在方法参数上使用“final”可以帮助您第一眼了解方法的输出,并引起对那些非最终参数的注意。 (3认同)

Rah*_*thy 18

考虑foo()的这种实现:

public void foo(final String a) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.print(a);
        }
    }); 
}
Run Code Online (Sandbox Code Playgroud)

因为Runnable实例会比方法更长,所以如果没有final关键字,这将无法编译- final告诉编译器可以安全地获取引用的副本(稍后引用它).因此,它是被认为是最终的参考,而不是价值.换句话说:作为一个来电者,你不能搞砸任何东西......

  • 但这并不是“因为 Runnable 实例的寿命比该方法长”。对于任何匿名内部类都是如此。 (2认同)
  • 哦,现在在Java 8中,我们有了有效的最终概念。 (2认同)