【问题标题】:When I define an interface method's parameters final do I need to repeat final in the implementations? [duplicate]当我定义接口方法的参数 final 时,我需要在实现中重复 final 吗? [复制]
【发布时间】:2013-12-17 13:02:46
【问题描述】:

那么在下面的情况下我需要重复final吗?

interface Foo {

    void meth(final Bar bar);
}

public Baz implements Foo {

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

这个问题不仅是接口继承,还有类继承——我猜答案是一样的

【问题讨论】:

  • 您有什么理由不能直接点击编译并亲自查看?
  • final 不是方法签名的一部分。它在您的接口定义中是多余的。
  • 阅读Java中signature的定义——它基于方法名和参数类型,没有别的。
  • @SameerSawla:是的,这就是为什么我说“final 不是 方法 签名的一部分”;)
  • @Mr_and_Mrs_D:但它没有记录任何内容... ;) final 是一个内部实现细节。

标签: java inheritance final


【解决方案1】:

是的,如果您希望编译器确保这些参数永远不会在 current 方法中重新分配,您确实需要将方法参数重新声明final。这在覆盖接口和类定义时都成立。

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

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

因此,在抽象方法签名中使用final 参数没有任何目的,既不是真实的也不是记录的:因为Java 实现方法调用是通过按值调用 而不是通过引用,final 修饰符永远不会影响实现方法范围之外的代码。因此,如果重新分配方法参数变量只是方法实际实现的细节。因此,我个人永远不会使用它来定义类或接口中的抽象方法。允许但没有意义。

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

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

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

【讨论】:

  • -1 "是的,您必须再次声明它。对于接口和类定义。" - 不适合界面!请参阅 Oli Charlesworth 的第一条评论。它与编译时信息无关。
  • 好吧,评论没有抓住重点。方法或参数注释都不是方法签名的一部分。重写方法时仍然可以保留此类信息。您可能想阅读 Java 语言规范。
  • @alfasin:我认为“必须”,因为接口中的final 与实现无关(因为它是多余的),所以如果你希望编译器强制执行不变性实现,你也需要final
  • @OliCharlesworth 确切地说,这就是为什么开发人员“必须”将final 关键字与任何实现(类)一起使用——而不是与接口一起使用。这个答案充满了错误:1.“子类”是一个用于继承的术语,而不是接口实现。 2. 这与字节码和编译时信息无关。 3. 内部类与它无关。等等。它所要做的就是 JLS 中的定义,讽刺的是,在我已经提供了链接之后,raphw 指示我阅读......
  • 这个问题没有其他答案。那么我在哪里复制了答案?即使我提供了尽可能完整的答案,即使我是从其他地方获得的,那不是很好吗?完成 JLS 后,您可能会阅读一些有关堆栈溢出的信息。我将自豪地对堆栈溢出进行第一次否决票。
猜你喜欢
  • 2012-05-14
  • 2011-04-17
  • 2014-01-14
  • 2013-09-06
  • 1970-01-01
  • 2012-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多