将Java方法参数作为最终参数


91

final下面的代码之间有什么区别?将参数声明为是有什么好处final

public String changeTimezone( Timestamp stamp, Timezone fTz, Timezone toTz){  
    return ....
}

public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
        final Timezone toTz){
    return ....
}

4
有些代码分析器会警告是否重复使用或重新分配参数。(与局部变量相同)恕我直言,如果发现不希望更改它们,这是捕获此类参数的更好方法。
彼得·劳瑞


我觉得Java默认会将所有输入法参数设置为final。然后,如果要修改参考,则必须手动进行。这样,内factor感会阻止很多这样的情况。
Sid

Answers:


131

由于形式化方法参数是局部变量,因此仅当内部匿名类被声明为final时,才可以从内部匿名类访问它们。

这样可以避免在方法体中声明另一个局部最终变量:

 void m(final int param) {
        new Thread(new Runnable() {
            public void run() {
                System.err.println(param);
            }
        }).start();
    }

27
+1:这是一个重要的用例,也是您唯一需要的时间。(在它只是一个什么样的方便,帮助程序员事休息的时间。)
多纳尔研究员

3
请问这背后的原因?
KodeWarrior 2014年

20
不再需要与Java 8
阿米特Parashar


3
@AmitParashar是的,但是Java 8 只是使您不必每次必须在内部类中使用变量时都必须使用关键字 “ final” ...实际上,编译器只是使最终性隐含,您仍然需要将变量有效地定为 final ...因此,如果以后尝试分配给它,您仍然会遇到编译时错误!Java 8SNEAK 100 :)
varun

38

摘自final关键字的最终词

最终参数

以下示例声明了最终参数:

public void doSomething(final int i, final int j)
{
  // cannot change the value of i or j here...
  // any change would be visible only inside the method...
}

在这里使用final来确保方法不会意外重置两个索引i和j。这是一种防止错误更改参数值的隐患的简便方法。一般而言,短方法是防止此类错误的更好方法,但是最终参数可能是编码风格的有用补充。

请注意,最终参数不被视为方法签名的一部分,并且在解决方法调用时,编译器将忽略它们。可以将参数声明为final(或不声明),而对方法的覆盖方式没有影响。


17
在此示例中,使用对象而不是基元可能会更好,因为基元更改始终仅在方法内部可见。对于对象,您仍然可以更改它们。您只是不能指向一个新对象。实际上,我现在考虑了一下,与将其遗漏相比,final并没有真正改变任何东西,除了使用AIC保存变量声明并让编译器指出由于某些原因您不想修改的参数意外修改之外, 。
罗伯·格兰特

26

最终值可防止您为变量分配新值,这有助于捕捉错别字。从风格上讲,您可能希望保持接收到的参数不变,仅将其分配给局部变量,因此final将有助于实施该样式。

必须承认,我很少记得使用final作为参数,也许我应该这样做。

public int example(final int basicRate){
    int discountRate;

    discountRate = basicRate - 10;
    // ... lots of code here 
    if ( isGoldCustomer ) {
        basicRate--;  // typo, we intended to say discountRate--, final catches this
    }
    // ... more code here

    return discountRate;
}

1
将参数声明为final的一个很好的例子。我对此很偏爱,但对于3个以上的参数也很满意。
JoseHdez_2

14

它并没有太大的区别。这只是意味着您不能写:

stamp = null;
fTz = new ...;

但您仍然可以写:

stamp.setXXX(...);
fTz.setXXX(...);

这主要是向维护程序员提示的,您将不会在方法中间不明显的地方给参数分配新值,因此可能会引起混淆。


3

当在Java中将final关键字用于参数/变量时,将引用标记为final。如果将对象传递给另一种方法,则系统会创建参考变量的副本并将其传递给该方法。通过将新引用标记为最终标记,可以保护它们免于重新分配。有时将其视为一种良好的编码习惯。


1
我必须添加一些内容:如果参数是原始参数,则看不到任何差异。此外,如果参数是Collections(对象列表...),则添加final不能阻止对其进行修改。
Sam003

1
不变性始终是理想的特性。Java没有开箱即用。使变量最终确定至少可以确保引用完整性。
2015年

1
我同意。但是,如果我们真的想实现对象的不变性,则可以尝试进行深度克隆。
Sam003

2

对于此方法的主体,final关键字将防止意外地重新分配参数引用,从而在这些情况下产生编译错误(大多数IDE会立即抱怨)。有人可能会争辩说,final只要有可能,一般情况下使用它就可以加快速度,但是在最近的JVM中并非如此。


2

我看到了两个优点:

1 将方法参数标记为final可以防止在方法内部重新分配参数

从你的例子

    public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
            final Timezone toTz){
    
    // THIS WILL CAUSE COMPILATION ERROR as fTz is marked as final argument

      fTz = Calendar.getInstance().getTimeZone();     
      return ..
    
    }

在一个复杂的方法中,将参数标记为final将有助于意外地将这些参数解释为方法的局部变量,而重新分配为编译器将标记这些情况,如示例所示。

2 将参数传递给匿名内部类

由于形式化方法参数是局部变量,因此仅当内部匿名类被声明为final时,才可以从内部匿名类访问它们。


1

-过去(在Java 8之前:-))

扩展使用“ final”关键字会影响内部匿名类的方法变量的可访问性。

-在现代(Java 8+)的lanaguage中,不需要这种用法:

Java引入了“有效的最终”变量。如果代码不暗示变量值的更改,则将局部变量和方法参数假定为最终变量。因此,如果您在Java8 +中看到这样的关键字,则可以认为它是不必要的。引入“有效最终”使我们在使用lambda时键入的代码更少。


0

它只是Java中的一种结构,可帮助您定义合同并遵守合同。这里有类似的讨论:http : //c2.com/cgi/wiki?JavaFinalConsideredEvil

顺便说一句-(如twiki所言),如果您遵循良好的编程原则,并且需要重新分配/重新定义传入的参数引用,则将args标记为final通常是多余的。

在最坏的情况下,如果您确实重新定义了args引用,则它不会影响传递给函数的实际值-因为仅传递了引用。


0

我说的一般是将变量和字段标记为final-不仅适用于方法参数。(最终标记方法/类是完全不同的东西)。

这对您的代码的读者/未来维护者是有帮助的。加上合理的变量名,对代码的阅读者很有帮助,让他们放心查看/理解问题中的变量代表什么-并向读者保证,只要您看到变量在相同范围内,含义就将保留相同,因此他不必费力地总是想出变量在每种情况下的含义。我们已经看到了太多的变量“重用”滥用,即使是很短的代码段也很难理解。


-3

final关键字阻止您为该参数分配新值。我想用一个简单的例子解释一下

假设我们有一个方法

method1(){

日期dateOfBirth =新日期(“ 1/1/2009”);

method2(dateOfBirth);

method3(dateOfBirth); }

public mehod2(Date dateOfBirth){
....
....
....
}

public mehod2(Date dateOfBirth){
....
....
....
}

在上述情况下,如果在方法2中为“ dateOfBirth”分配了新值,则这将导致方法3输出错误。因为传递给method3的值与传递给method2之前的值不同。因此,要避免将此最终关键字用于参数。

这也是Java Coding最佳实践之一。


5
那不是很正确。即使参数dateOfBirth在method2()中更改为另一个值,这也对method2()没有影响,因为Java按值传递而不是按引用传递。
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.