使用 final 来限制继承和覆盖

final 类

当在 class 声明中使用时,final 修饰符会阻止其他类被声明为 extend 类。final 类是继承类层次结构中的叶子类。

// This declares a final class
final class MyFinalClass {
    /* some code */
}

// Compilation error: cannot inherit from final MyFinalClass
class MySubClass extends MyFinalClass {
    /* more code */
}

final 类的用例

最终类可以与 private 构造函数结合使用,以控制或阻止类的实例化。这可以用来创建一个只定义静态成员的所谓实用程序类; 即常数和静态方法。

public final class UtilityClass {

    // Private constructor to replace the default visible constructor
    private UtilityClass() {}

    // Static members can still be used as usual
    public static int doSomethingCool() {
        return 123;
    }

}

不可变类也应该声明为 final。 (不可变类是在创建实例后无法更改的类;请参阅 I mmutable Objects 主题。)通过这样做,你无法创建不可变类的可变子类。这将违反 Liskov 替代原则 ,该原则要求子类型应遵守其超类型的行为合同

从实际角度来看,将不可变类声明为 final 可以更容易推理程序行为。它还解决了在安全沙箱中执行不受信任的代码的情况下的安全问题。 (例如,由于 String 被声明为 final,一个受信任的类不需要担心它可能被欺骗接受可变子类,然后不可信的调用者可能会偷偷地改变它。)

final 类的一个缺点是它们不适用于一些模拟框架,如 Mockito。更新:Mockito 版本 2 现在支持模拟最终类。

最后的方法

final 修饰符也可以应用于方法,以防止它们在子类中被覆盖:

public class MyClassWithFinalMethod {

    public final void someMethod() {
    }
}

public class MySubClass extends MyClassWithFinalMethod {

    @Override
    public void someMethod() { // Compiler error (overridden method is final)
    }
}

当你想要限制子类在类中可以更改的内容而不完全禁止子类时,通常会使用最终方法。

final 修饰符也可以应用于变量,但 final 对变量的含义与继承无关。