当我定义一个接口方法的参数final时,我需要在实现中重复final吗?

时间:2013-12-01 22:06:31

标签: java inheritance final

所以我需要在下面的情况下重复最终决定吗?

interface Foo {

    void meth(final Bar bar);
}

public Baz implements Foo {

    @Override
    void meth(/* is it final ?*/ Bar bar){}
}

问题不仅是接口继承,还有类继承 - 我想答案是相同的

1 个答案:

答案 0 :(得分:6)

是的,如果希望编译器确保在当前方法中永远不会重新分配这些参数,则需要重新声明方法参数为final。这在覆盖接口和类定义时都适用。

原因很简单:这是Java语言规范中指定的行为。但是,编译器甚至无法检查是否重新分配final参数,即使它想要:

方法范围中变量的final修饰符实际上未转换为字节代码或在别处写入Java类文件格式。它在编译特定类或接口后基本消失,并且在编译后无法跟踪。由于每个类和接口都是独立于其他类和接口编译的,因此编译器或JVM运行时验证程序无法确保在子类或接口实现中为final参数分配了新值。它只在单个类的编译中,Java编译器可以确保不会发生这样的分配。因此,final参数的声明对于类是本地的,并且不可能在将来更改此行为或通过使用运行时反射来查找此功能。

因此,在抽象方法签名中使用final参数不能达到目的,既不是真实的也不是纪录片:由于Java通过调用来实现方法调用值而不是引用,final修饰符永远不会影响实现方法范围之外的代码。因此,如果重新分配方法参数变量,则仅仅是方法实际实现的细节。因此,我个人从不使用它来定义类或接口中的抽象方法。这是允许的,但毫无意义。

在非抽象方法定义中,声明方法变量final仅用于以下两个目的之一:

  • 您想在匿名类的范围内使用变量。
  • 您希望编译器检查您是否意外重新分配变量。这在处理类似类型的许多变量时特别有用。在这里,final修饰符也可用作某种文档。

更新:从Java 8开始,如果方法参数是合成(未在源代码中表示,强制(隐式出现在源代码中,例如lambda表达式的this引用)或者它是final。但这不会影响重写方法,其中需要为此重复final声明此外,Java语言没有注意这些标志,只有元框架才能读取这些标志来实现它们可能对这些标志作出反应的逻辑。