使用 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
对变量的含义与继承无关。