原文: https://howtodoinjava.com/oops/method-overloading-and-overriding-rules-in-java/

方法重载和覆盖(换句话说,Java 中的多态)既不是一个非常困难的概念,也不是一个非常未知的主题。 但是,我将在本文中介绍这个主题,因为同时使用多个代码示例在 Java 面试中测试此类概念时,很容易犯错误。 我在这里没有给出任何新概念,但是我打算修改您有关 Java 中方法重载和覆盖规则的现有知识。

方法重载规则

重载 Java 中的任何方法时,请牢记以下规则:

1)Java 中重载方法的第一个重要规则是更改方法签名。 方法签名由变量数量,变量类型和变量顺序(如果它们是不同类型)组成。

  1. public class DemoClass {
  2. // Overloaded method
  3. public Integer sum(Integer a, Integer b) {
  4. return a + b;
  5. }
  6. // Overloading method
  7. public Integer sum(Float a, Integer b) { //Valid
  8. return null;
  9. }
  10. }

2)方法的返回类型从来都不是方法签名的一部分,因此仅更改方法的返回类型并不等于方法重载

  1. public class DemoClass {
  2. // Overloaded method
  3. public Integer sum(Integer a, Integer b) {
  4. return a + b;
  5. }
  6. // Overloading method
  7. public Float sum(Integer a, Integer b) { //Not valid; Compile time error
  8. return null;
  9. }
  10. }

3)重载方法时,也不会考虑方法引发的异常。 因此,您的重载方法会抛出相同的异常,不同的异常,或者它根本不会引发任何异常。 对方法加载完全没有影响。

  1. public class DemoClass {
  2. // Overloaded method
  3. public Integer sum(Integer a, Integer b) throws NullPointerException{
  4. return a + b;
  5. }
  6. // Overloading method
  7. public Integer sum(Integer a, Integer b) throws Exception{ //Not valid; Compile time error
  8. return null;
  9. }
  10. }

阅读更多:什么是 Java 中的多态

方法覆盖规则

我们在上面阅读了方法重载的规则,现在是时候列出在覆盖 Java 中的方法时应记住的规则了。

1)覆盖方法和被覆盖方法中的参数列表必须完全相同。如果它们不匹配,则最终将得到重载方法。

2)覆盖方法的返回类型可以是在被覆盖方法中声明的返回类型的子类。

  1. public class SuperClass {
  2. //Overriden method
  3. public Number sum(Integer a, Integer b) {
  4. return a + b;
  5. }
  6. }
  7. class SubClass extends SuperClass {
  8. //Overriding method
  9. @Override
  10. public Integer sum(Integer a, Integer b) { //Integer extends Number; so it's valid
  11. return a + b;
  12. }
  13. }

3)在所有规则中,不能以任何方式在 Java 中覆盖私有,静态和最终方法。 就如此容易 !!

  1. public class SuperClass {
  2. private Integer sum(Integer a, Integer b) { //private method; overriding not possible
  3. return a + b;
  4. }
  5. }
  6. class SubClass extends SuperClass {
  7. //Overriding method
  8. public Integer sum(Integer a, Integer b) {
  9. return a + b;
  10. }
  11. }

4)覆盖方法无法引发层次结构中比覆盖方法所引发的异常高的受检的异常。 例如,假设父类中的覆盖方法抛出FileNotFoundException,子类中的覆盖方法抛出FileNotFoundException; 但不允许抛出IOExceptionException,因为IOExceptionException的层次结构较高,即FileNotFoundException的超类。

此外,您可以从覆盖方法中省略异常声明。 允许且完全有效。 同样,无论覆盖方法是否声明该异常,覆盖方法都可以引发任何非受检的(运行时)异常。

  1. public class SuperClass {
  2. //Overriden method
  3. public Integer sum(Integer a, Integer b) throws FileNotFoundException {
  4. return a + b;
  5. }
  6. }
  7. class SubClass extends SuperClass {
  8. //Overriding method
  9. public Integer sum(Integer a, Integer b) throws IOException { //Not valid; Compile time error
  10. return a + b;
  11. }
  12. //Exception IOException is not compatible with throws clause in SuperClass.sum(Integer, Integer)
  13. public Integer sum(Integer a, Integer b) { //It's valid; Don't declare the exception at all is permitted.
  14. return a + b;
  15. }
  16. }

5)另请注意,覆盖方法不能缩小被覆盖方法的访问范围。 简而言之,如果父类中的被覆盖方法受到保护,则子类中的覆盖方法不能为私有。 它必须是受保护的(相同的访问权限)或公共的(更广泛的访问权限)。

  1. public class SuperClass {
  2. //Overriden method
  3. protected Integer sum(Integer a, Integer b) {
  4. return a + b;
  5. }
  6. }
  7. class SubClass extends SuperClass {
  8. //Overriding method
  9. //Not valid; Compile time error "Cannot reduce the visibility of the inherited method from SuperClass"
  10. private Integer sum(Integer a, Integer b) {
  11. return a + b;
  12. }
  13. }

在父类和子类的术语上进行讨论时,不再重复方法覆盖是合法的。 它不会在同一个类中发生。

要验证您是否正确覆盖了方法,只需在覆盖方法上使用注解@Override。 它将为您验证所有方法替代规则。 如果有任何问题,将导致编译时错误。

阅读更多: Java 面试问题

这就是这个简单而重要的概念的全部内容,可以帮助您熟练掌握 Java 和面向对象编程的基础知识。

祝您学习愉快!

参考: Oracle 博客