繁体   English   中英

将java方法参数设为final

[英]Making java method arguments as final

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 ....
}

由于形式方法参数是一个局部变量,只有当它们声明为 final 时,您才能从内部匿名类访问它们。

这使您无需在方法主体中声明另一个局部最终变量:

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

摘录自The final word on the 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 阻止您为变量分配新值,这有助于发现拼写错误。 从风格上讲,您可能希望保持接收的参数不变并仅分配给局部变量,因此 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;
}

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

stamp = null;
fTz = new ...;

但你仍然可以写:

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

这主要是对跟随您的维护程序员的一个提示,即您不会在方法中间的某个地方为参数分配一个新值,因为它不明显,因此可能会导致混淆。

在 Java 中用于参数/变量的 final 关键字将引用标记为 final。 如果将对象传递给另一个方法,系统会创建引用变量的副本并将其传递给该方法。 通过将新引用标记为 final,您可以保护它们免于重新分配。 它有时被认为是一种很好的编码实践。

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

列出了我看到的两个优点:

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 时,您才能从内部匿名类访问它们。

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

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

- 在现代(Java 8+)语言中,不需要这样的用法:

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

它只是 Java 中的一种结构,可帮助您定义契约并坚持下去。 这里有一个类似的讨论: http : //c2.com/cgi/wiki?JavaFinalConsideredEvil

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

在最坏的情况下,如果你重新定义了 args 引用,它不会影响传递给函数的实际值——因为只传递了一个引用。

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

这对你的代码的读者/未来的维护者有好处。 再加上一个合理的变量名称,它有助于让代码的读者看到/理解所讨论的变量所代表的内容,并让他们放心——而且让读者放心,只要您在同一范围内看到变量,意义就会保持不变相同,因此(她)他不必总是挠头去弄清楚变量在每种情况下的含义。 我们已经看到太多滥用变量“重用”的情况,这使得即使是简短的代码片段也难以理解。

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

假设我们有一个方法

方法1(){

日期 dateOfBirth =new Date("1/1/2009");

方法2(出生日期);

方法3(出生日期); }

公共方法2(出生日期){
....
....
....
}

公共方法2(出生日期){
....
....
....
}

在上述情况下,如果在方法 2 中为“dateOfBirth”分配了新值,那么这将导致方法 3 的输出错误。 因为传递给method3的值不是传递给method2之前的值。 所以为了避免这个 final 关键字用于参数。

这也是 Java 编码最佳实践之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM