Java异常之---子类重写方法调用父类方法,父类发生异常怎么办?

本文深入探讨Java异常机制中,子类方法重写父类方法时的异常处理规则,特别是子类异常范围小于父类异常的情况,并通过代码示例说明如何正确处理这种情况。

总所周知,在Java异常机制中,如果父类的一个方法抛出了异常,那么当有子类继承自这个父类时,如果重写了这个方法,那么它抛出的异常范围有三种情况:
情况一: 和父类异常一致
情况二:比父类异常范围小(即为父类异常的子类)
情况三:不抛出任何异常

针对情况二:

那么问题来了,如果在子类中利用super关键字调用父类的同名方法时,会怎样?

代码如下:
这里我自定义了两个异常,它们为父子类关系。
定义了两个实体类,它们为父子关系。

package com.calarqiang.exception;

import java.io.IOException;

/**
 * @author yq
 * @create 2021-01-27-19:30
 */
 
 //自定义异常父类
public class MyException extends IOException {
  public MyException(){

  }
  public MyException(String message){
      super(message);
  }
}

//自定义异常子类,继承自异常父类
class SonException extends MyException{
    public SonException(){}
    public SonException(String message){
        super(message);
    }
}

//实体父类,Person
class Person{
    public void run ()throws MyException {
        throw new MyException("父类抛出异常!");
    }
}

//实体子类,继承自实体父类Person
class Son extends Person{
    public void run() throws SonException{
    //问题就在这,这里必须进行处理,不能不处理,因为父类异常大于子类异常
    //而子类抛出的异常声明比父类的小,它不包含父类异常,因此必须进行try-catch处理!!!
        try {
            super.run(); 
        } catch (MyException e) {
            System.out.println(e);
        }
        throw new SonException("子类抛出异常!!");
    }
}

 class Test{
    public static void main(String[] args) {
        Son son = new Son();
        try {
            son.run();
        } catch (SonException e) {
            System.out.println(e);
        }
    }
}

如上所述:由于子类抛出的异常范围必须小于或者等于父类的异常范围,而如果子类的重写方法调用父类的重写方法时,这时父类要抛出异常,而子类抛出的异常声明又小于父类的异常,因此无法处理父类的异常,所以必须在子类方法中就用try-catch处理父类的异常。

其它几种情况:

而针对情况一来说,就可以不用处理了,直接在调用子类方法处一起处理子父类异常。
针对情况三来说,由于子类不能抛异常,那么调用父类就必须在方法体内部处理异常,同时自身如果抛出异常的话,也必须处理!

那么为什么父类的就要比子类大呢?

不能非黑即白!因为可以这样想:
如果一个父类对象作为一个类中的方法参数,当调用该类的方法时,抛出异常,此时在方法体内处理它,但是如果传递的是一个子类对象进去(多态),那么当此时子类的异常比父类大,那么方法内部的try-catch就无法处理捕获它,从而发生错误。因此就要比父类异常小!


这里有另外一个知识点:
关于检查性型异常和非检查型异常

  • 检查型异常
    其它的异常则称为检查型异常。
  • 非检查型异常
    所有的派生于Error类或者RuntimeException类的异常称为非检查型异常。

对于检查型异常,要么在方法内部处理掉,要么声明(throws)一个方法内部可能出现的所有检查型异常。
如果调用了一个抛出检查型异常的方法

  1. 就必须处理这个异常
  2. 继续传播这个异常。
    具体做法就是捕获知道如何处理的异常,而继续传播哪些不知道怎么处理的异常!

避免声明非检查型异常,因为它完全可以由编程者仔细检查避免!

Java 中,当子类重写父类方法后,**默认情况下调用方法会执行子类的实现版本**。这是因为 Java方法调用机制采用的是运行时的动态绑定(也称为后期绑定或运行时多态),即根据对象的实际类型来决定调用哪个方法[^4]。 例如,若 `Student` 类重写了 `Person` 类中的 `message()` 方法,则通过 `Student` 实例调用 `message()` 时,会执行 `Student` 类中的实现,输出 `"This is student class"`,而不是父类 `Person` 的实现[^4]。 然而,子类中可以通过 `super` 关键字显式调用父类中被重写方法。例如,在子类方法中使用 `super.message()` 可以明确调用父类版本的 `message()` 方法,即使它已经被重写。这种机制允许子类在需要时保留并使用父类的功能,同时扩展或修改其行为[^3]。 ### 示例代码 ```java abstract class Person { public void message() { System.out.println("This is person class"); } } class Student extends Person { @Override public void message() { System.out.println("This is student class"); } public void callParentMessage() { super.message(); // 显式调用父类的 message 方法 } public static void main(String[] args) { Student s = new Student(); s.message(); // 输出 "This is student class" s.callParentMessage(); // 输出 "This is person class" } } ``` 上述代码展示了子类如何通过 `super` 调用父类中被重写方法。尽管 `message()` 在 `Student` 类中被重写,但在 `callParentMessage()` 方法中仍能调用到 `Person` 类的 `message()` 实现[^3]。 ### 总结 - 子类重写父类方法后,默认调用的是子类自身的实现。 - 使用 `super` 关键字可以在子类中显式调用父类的实现版本。 - Java 的动态绑定机制确保了运行时根据对象的实际类型选择合适的方法版本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值