Java throw和throws的用法
在程序中,可能存在需要使用同一处理逻辑处理多个位置的异常的情况。如果采用捕获并处理的方式,程序中可能会出现多处代码完全相同的 catch 语句块。当异常的处理逻辑发生变化时,需要逐个查找这些 catch 语句块进行修改,这会影响代码的可维护性。
在这种场景下,可以采用声明和抛出异常的方式,不在当前位置处理异常,而是将异常对象交给方法的调用者,先在合适的位置捕获这些异常,再进行统一处理。另外,如果某个方法不知道应该如何处理某个异常,那么也可以使用声明和抛出的方式,将异常交给方法的调用者处理。
在 Java 中,可以使用 throw 与 throws 配合实现异常的声明和抛出,语法格式如下:
在使用 throw 与 throws 时需要注意如下规则:
【实例】声明和抛出异常。
在这种场景下,可以采用声明和抛出异常的方式,不在当前位置处理异常,而是将异常对象交给方法的调用者,先在合适的位置捕获这些异常,再进行统一处理。另外,如果某个方法不知道应该如何处理某个异常,那么也可以使用声明和抛出的方式,将异常交给方法的调用者处理。
在 Java 中,可以使用 throw 与 throws 配合实现异常的声明和抛出,语法格式如下:
方法签名 throws 异常类型{ throw 异常对象; }
- throw:放入方法中,用于抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
- throws:放入方法声明中,用于告知当前方法的调用者,当前方法中可能会出现某个类型的异常。
在使用 throw 与 throws 时需要注意如下规则:
- 如果当前方法中可能会出现某种受检异常(非 RuntimeException 类及其子类异常),并且没有使用 try-catch 语句块进行处理,那么方法声明中必须使用 throws 通知方法的调用者,当前方法可能会抛出该类型的抽检异常,未使用 throws 会导致编译无法通过;
- 如果当前方法中可能会出现某种非受检异常(RuntimeException 类及其子类异常),那么编译器不强制必须使用 throws,但从代码严谨性的角度来看,应该主动使用 throws 声明可能会出现该类型的异常;
- throws 仅代表一种可能性,并不代表一定会出现该类型的异常;
- throws 后面可以出现多种异常类型,异常类型之间使用英文逗号间隔;
- 执行 throw,相当于当前代码出现了异常对象,将触发 Java 的异常机制,throw 后续的代码将不会被执行。
【实例】声明和抛出异常。
package chapter6; public class Test { public static void main(String[] args) { try { double random = Math.random(); if (random > 0.5) { methodA(); } else { methodB(); } } catch (RuntimeException e) { // 处理非受检异常 System.out.println(e.getMessage()); } catch (Exception e) { // 处理受检异常 System.err.println(e.getMessage()); // 抛出受检异常,需要在方法声明中使用throws } } public static void methodA() throws Exception { // 主动抛出受检异常 throw new Exception("抛出的受检异常"); } public static void methodB() { // 主动抛出非受检异常 throw new RuntimeException("抛出的非受检异常"); } }在继承或接口实现中,子类可能会重写从父类继承的方法,实现类可能会实现父接口中定义的抽象方法。如果父类或父接口中的方法使用 throws 声明或抛出了异常,那么重写或实现这些父类方法需要注意如下原则:
- 重写或实现的方法使用throws声明和抛出的异常类型必须小于或等于父类抛出的异常类型,也就是说,可以是与父类方法一致或父类方法抛出异常类型的子类;
- 如果父类方法抛出多个异常,那么重写或实现的方法必须抛出这些异常的一个子集,而不能抛出新异常。