前提
Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行Debug。
本文主要介绍一个使用反射一定会遇到的问题-反射调用异常处理。
反射调用异常处理
反射调用出现异常的方法主要考虑下面的情况:
属性操作:java.lang.reflect.Field#set(Object obj, Object value)和java.lang.reflect.Field#get(Object obj)。
构造器调用:java.lang.reflect.Constructor#newInstance(Object ... initargs)。
方法调用:java.lang.reflect.Method#invoke(Object obj, Object... args)。
处理属性操作异常
先看设置属性的方法:
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException
实际上,通过方法注释可以得知会抛出四种异常:
IllegalAccessException:非法访问异常,注意它是检查(checked)异常,也就是需要显示捕获,此异常会在修饰符禁用访问的时候抛出,可以通过setAccessible(true)抑制修饰符检查来避免抛出此异常。
IllegalArgumentException:非法参数异常,它是运行时异常,当入参实例obj不是当前Field所在类(包括父类、子类和接口)的时候会抛出此异常。
NullPointerException:空指针异常,当入参实例obj为null的时候会抛出此异常。
ExceptionInInitializerError:初始化器调用异常导致的错误,如果由于set(Object obj, Object value)方法引发的初始化失败会包装成ExceptionInInitializerError,此异常的父类为Error,常见的发生情况就是静态成员或者静态代码块依赖到反射属性设置。
前面三种异常都很好理解,最后一个ExceptionInInitializerError可能有点陌生,它的抛出条件是:在静态代码块初始化解析过程总抛出异常或者静态变量初始化的时候抛出异常。笔者尝试了很多例子都没办法造出案例,从Stackoverflow找到一个例子:
public cl