168

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

public void foo(final String a, final int[] b, final Object1 c){
}

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

4

9 回答 9

220

Java 总是在将参数发送到方法之前制作一个副本。这意味着 final 对调用代码没有任何区别。这仅意味着在方法内部不能重新分配变量。

请注意,如果您有最终对象,您仍然可以更改对象的属性。这是因为 Java 中的对象实际上是指向对象的指针。并且只有指针被复制(并且将在您的方法中是最终的),而不是实际的对象。

于 2010-02-10T12:08:28.333 回答
94

在某些情况下,您需要将其声明为 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;
}

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

于 2010-02-10T12:16:45.837 回答
63

Java 只是按值传递。(或更好 - 按值传递引用)

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

因此,如果您更改对象的状态,它会反映到引用它的所有其他变量。但是,如果您将新对象(值)重新分配给参数,则指向该对象(值)的其他变量不会被重新分配。

于 2010-02-10T12:08:01.987 回答
48

方法参数上的final关键字对调用者毫无意义。它对正在运行的程序也毫无意义,因为它的存在或不存在不会改变字节码。它仅确保在方法中重新分配参数变量时编译器会抱怨。就这样。但这已经足够了。

一些程序员(比如我)认为这是一件非常好的事情,并且final几乎可以用于每个参数。它使理解一个长的或复杂的方法变得更容易(尽管有人可能会争辩说应该重构长而复杂的方法。)它还突出了没有标记的方法参数final

于 2013-08-09T22:50:40.243 回答
23

考虑 foo() 的这个实现:

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

因为Runnable实例的寿命会比方法长,所以如果没有final关键字, this 将无法编译 --final告诉编译器获取引用的副本是安全的(稍后引用它)。因此,参考被认为是最终的,而不是value。换句话说:作为呼叫者,你不能搞砸任何事情......

于 2010-02-10T12:14:21.813 回答
2

final意味着一旦分配了该变量,您就无法更改该变量的值。

同时,在这些方法中使用final作为参数意味着它不允许程序员在方法执行期间更改它们的值。这仅意味着在方法内部不能重新分配最终变量。

于 2015-03-18T03:45:20.570 回答
1

如果将任何参数声明为 final,则无法更改它的值。

class Bike11 {  
    int cube(final int n) {  
        n=n+2;//can't be changed as n is final  
        n*n*n;  
     }  
    public static void main(String args[]) {  
        Bike11 b=new Bike11();  
        b.cube(5);  
    }  
}   

输出:编译时错误

更多详情请访问我的博客:http: //javabyroopam.blogspot.com

于 2015-04-05T17:37:49.313 回答
1

不需要方法输入参数中的 final 关键字。Java 创建了对象引用的副本,因此将 final 放在它上面并不会使对象成为最终对象,而只是引用,这没有意义

于 2015-11-11T16:40:58.810 回答
0

字符串是不可变的,因此实际上您不能在之后更改字符串(您只能使保存字符串对象的变量指向不同的字符串对象)。

但是,这不是您可以将任何变量绑定到final参数的原因。所有编译器检查的是参数没有方法中重新分配。这有利于文档的目的,可以说是很好的风格,甚至可以帮助优化字节码以提高速度(尽管这在实践中似乎没有多大作用)。

但是,即使您确实在方法中重新分配了参数,调用者也不会注意到这一点,因为 java 会按值传递所有参数。序列后

  a = someObject();
  process(a);

a 的字段可能已更改,但 a 仍然是以前的对象。在传递引用的语言中,这可能不是真的。

于 2010-02-10T12:15:11.207 回答