java反射只能获取方法声明的throws异常类型,无法获取方法体内实际throw的异常;通过method.getexceptiontypes()获取声明异常数组,再按“继承exception但不继承runtimeexception且不继承error”筛选可得受检异常。

Java 中无法通过反射直接获取方法体内部 抛出(throw) 的受检异常类型,只能获取该方法在 声明(throws) 子句中显式列出的受检异常类型。
获取方法声明的 throws 异常类型
使用 Method.getExceptionTypes() 方法,它返回一个 Class>[] 数组,包含该方法签名中 throws 子句声明的所有异常类型(包括受检和非受检异常,但通常关注 Exception 及其子类)。
- 该数组顺序与源码中
throws列表顺序一致 - 只反映编译期声明,不反映方法体内实际
throw的异常(那些无法被反射捕获) - 运行时异常(如
RuntimeException及其子类)也会出现在结果中,需手动过滤
区分受检异常与非受检异常
受检异常(checked exception)指继承自 Exception 但不继承自 RuntimeException 的类。可通过以下逻辑筛选:
clazz != RuntimeException.class && Exception.class.isAssignableFrom(clazz) && !RuntimeException.class.isAssignableFrom(clazz)- 更稳妥方式:用
Throwable.class.isAssignableFrom(clazz)确保是异常类型,再排除Error和RuntimeException及其子类
示例代码
假设有一个方法:
public void readFile() throws IOException, SQLException, IllegalArgumentException {}
反射获取并筛选受检异常:
Method m = clazz.getDeclaredMethod("readFile");
Class>[] declaredExceptions = m.getExceptionTypes();
List<class>> checkedExceptions = Arrays.stream(declaredExceptions)
.filter(clazz -> Exception.class.isAssignableFrom(clazz)
&& !RuntimeException.class.isAssignableFrom(clazz)
&& !Error.class.isAssignableFrom(clazz))
.collect(Collectors.toList());</class>
结果为 [IOException.class, SQLException.class];IllegalArgumentException 被过滤(它是 RuntimeException 子类)。
注意事项
- 泛型异常、类型擦除不影响
getExceptionTypes(),它返回的是原始类型(如MyException<string></string>擦除后仍是MyException.class) - 接口默认方法、静态方法、私有方法的
throws声明同样可被获取 - 若方法未声明
throws,返回空数组new Class[0]
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











