Java`final`方法:它承诺了什么?

在Java类中,可以将方法定义为final ,以标记此方法可能不会被覆盖:

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

这很清楚,它可能有助于防止意外覆盖或性能 - 但这不是我的问题。

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

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

final方法承诺什么样的“合同”?


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

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

有许多原因可以阻止某些东西被定制,其中包括:

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

  • 获取封装的数据 - 查看不可变的对象,其中的属性在构建时设置,并且不应该改变。 或从这些属性派生的计算值。 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
    

    最终方法承诺什么样的“合同”?

    换一种方式来看,任何非最终方法都可以隐式保证您可以用自己的实现覆盖它,并且该类仍将按预期工作。 如果你不能保证你的课程支持覆盖某个方法,那么你应该让它成为最终的。


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

    我同意,如果这些方法调用非最终方法, final标记方法并不能保证它们的行为在子类中是相同的。 如果行为确实需要修复,那么必须通过惯例和精心设计来实现。 并且不要忘记在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);
      }
    }  
    
    链接地址: http://www.djcxy.com/p/86599.html

    上一篇: Java `final` method: what does it promise?

    下一篇: How could I check if a number is a perfect square?