📜  我们可以覆盖Java中的 Final 方法吗?

📅  最后修改于: 2022-05-13 01:55:35.947000             🧑  作者: Mango

我们可以覆盖Java中的 Final 方法吗?

子类中的方法被称为 如果该方法具有与其超类中的方法相同的签名,则覆盖其超类中的方法。当子类的对象调用此方法时,将始终调用 Overridden 版本。换句话说,在超类中被覆盖的方法将被隐藏。

JVM 有两种选择,它可以调用存在于超类中的原始方法或存在于子类中的 Overridden 方法。由于后期绑定,这个决定是在运行时而不是在编译时做出的。

我们可以覆盖最终方法吗?

不,声明为 final 的方法不能被覆盖或隐藏。正是因为这个原因,一个方法只有在我们确定它是完整的时才必须声明为 final。

  • 值得注意的是,抽象方法不能被声明为 final,因为它们不完整,并且需要覆盖它们。
  • 方法在Java中被声明为 final 以防止子类覆盖它们并改变它们的行为,本文末尾讨论了这种工作的原因。
  • final 关键字的优点是它阻止开发人员有意或无意地更改出于安全或其他原因不应更改的方法的行为。

覆盖最终方法的结果

在下面的代码中:

  • IntegralOperations 类有两个方法,即执行预期操作的加法和减法。
  • 加法和减法都被声明为final。
  • 子类扩展 IntegralOperations 并尝试覆盖加法和减法。
Java
// Java Program to demonstrate result of overriding a final
// method
  
class IntegralOperations {
    
    // add declared as final
    final int add(int a, int b) { return a + b; }
    
    // subtract declared as final
    final int subtract(int a, int b) { return a - b; }
}
  
class child extends IntegralOperations {
  
    // try to override add
    @Override int add(int a, int b) { return a - b; }
  
    // try to override subtract
    @Override int subtract(int a, int b) { return a * b; }
}
  
public class Main {
    public static void main(String[] args)
    {
        child c1 = new child();
        System.out.println(c1.add(1, 4));
    }
}


输出

prog.java:13: error: add(int,int) in child cannot override add(int,int) in IntegralOperations
    @Override int add(int a, int b) { return a - b; }
                  ^
  overridden method is final
prog.java:16: error: subtract(int,int) in child cannot override subtract(int,int) in IntegralOperations
    @Override int subtract(int a, int b) { return a * b; }
                  ^
  overridden method is final
2 errors

为什么最后一个关键字会阻止覆盖?

一开始讨论要重写的方法遵循动态方法调度(后期绑定),但声明为最终的方法遵循静态绑定(早期绑定),这意味着方法定义将在编译时与主体分组-时间本身。

换句话说,JVM 必须确切地知道在编译时调用哪个方法。要实现这一点,对于每个最终方法定义必须有一个唯一的主体。但是如果允许覆盖,那么一个方法定义可以有多个主体,然后编译器将无法选择其中之一。

在上面的示例中可以看到这个问题,其中我们有两个主体用于加法和减法方法。这会提示编译器在编译时抛出错误。这样,final 关键字可以防止 Overriding 并保护方法的语义。