Java最后的方法:它承诺什么?

在一个Java类中,一个方法可以被定义为final ,以标记这个方法可能不被覆盖:

 public class Thingy { public Thingy() { ... } public int operationA() {...} /** this method does @return That and is final. */ public final int getThat() { ...} } 

这很清楚,可能有一些用途来防止意外的压倒性的,或者可能的performance – 但那不是我的问题。

我的问题是:从面向对象的angular度来看,我明白,通过定义一个方法final的类devise器承诺这种方法将始终如所述,或暗示的工作。 但是,如果这个方法正在做的更复杂,那么只是提供一个属性 ,这往往可能超出了类作者的影响。

句法约束对我来说很清楚,但是OOP意义上的含义是什么? 大多数课堂作者在这个意义上final被正确地使用了吗?

什么样的“契约” final方法承诺?

如前所述, final与Java方法一起使用来标记该方法不能被覆盖(对象范围)或隐藏(对于静态)。 这允许原始开发人员创build不能被子类更改的function,这是它提供的所有保证。

这意味着如果方法依赖于其他可定制的组件,如非公共的字段/方法,最终方法的function仍然可以定制。 这是好的,虽然(与多态),它允许部分定制。

有几个原因可以防止某些东西被定制,包括:

  • 性能 – 一些编译器可以分析和优化操作,特别是没有副作用的编译器。

  • 获取封装的数据 – 查看不可变的对象,在构build时设置它们的属性,不应该改变。 或从这些属性派生的计算值。 Java String类是一个很好的例子。

  • 可靠性和契约 – 对象由基元( intchardouble等)和/或其他对象组成。 并不是所有适用于这些组件的操作都应该适用,甚至在更大的对象中使用它们时也是合乎逻辑的。 使用final修饰符的方法可以确保。 Counter类就是一个很好的例子。


 public class Counter { private int counter = 0; public final int count() { return counter++; } public final int reset() { return (counter = 0); } } 

如果public final int count()方法不是final ,我们可以这样做:

 Counter c = new Counter() { public int count() { super.count(); return super.count(); } } c.count(); // now count 2 

或者像这样的东西:

 Counter c = new Counter() { public int count() { int lastCount = 0; for (int i = super.count(); --i >= 0; ) { lastCount = super.count(); } return lastCount; } } c.count(); // Now double count 

什么样的“契约”最后的方法承诺?

从另一个angular度来看,任何非最终方法都可以隐式保证你可以用你自己的实现来覆盖它,并且这个类仍然可以按照预期工作。 当你不能保证你的课程支持覆盖一个方法时,你应该把它做成最终的。

首先,您可以标记final非抽象类以及字段和方法。 这样整个class级不能被分类。 所以,课堂的行为将是固定的。

我同意,如果这些方法调用非最终方法, final标记方法并不能保证它们的行为在子类中是相同的。 如果行为确实需要固定下来,就必须通过惯例和精心devise来实现。 不要忘记在javadoc中这个概念!(java文档)

最后但并非最不重要的, final关键字在Java内存模型(JMM)中起着非常重要的作用。 JMM保证,为了实现final字段的可见性,您不需要适当的同步。 例如:

 class A implements Runnable { final String caption = "Some caption"; void run() { // no need to synchronize here to see proper value of final field.. System.out.println(caption); } } 

我不确定你可以对“最终”的使用做出任何断言,以及这将如何影响软件的整体devise合同。 你保证没有开发人员可以重写这个方法,并以这种方式使其合同无效。 但另一方面,最后的方法可能依赖于类或实例variables,其值由子类设置,并且可以调用覆盖的其他类方法。 所以最后是最多的一个非常弱的保证。

不,这不在课堂作者的影响之外。 您不能在您的派生类中重写它,因此它将执行基类作者所期望的。

http://download.oracle.com/javase/tutorial/java/IandI/final.html

值得注意的是它表明从构造函数调用的方法应该是final