method.invoke()抛出InvocationTargetException异常

文章目录

  • 背景
  • 代码
    • 自定义异常
    • 业务代码
    • 异常日志
    • 解决方案

背景

在做单元测试时候,在一个私有方法中抛出了自定义异常。使用method.invoke()之后,使用try{} catch (自定义异常){}进行捕获,竟然没有捕获到,最终定位到原因是:如果方法中直接抛出异常,通过反射进行调用时,会抛出InvocationTargetException异常

代码

自定义异常

public class MyException extends RuntimeException {

  String msg;

  MyException() {
    super();
  }

  MyException(String msg) {
    super(msg);
    this.msg = msg;
  }
}

业务代码

public class Test {

  public static void main(String[] args) throws Exception {
    Test t = new Test();
    Class clz = t.getClass();
    Method addMethod = clz.getDeclaredMethod("divde", int.class, int.class);
    System.out.println(addMethod.invoke(new Test(), 1, 0));
  }

  private double divde(int x, int y) {
    if (y == 0) {
      throw new MyException("除数不能为0");
    }
    return 1.0 * x / y;
  }
}

异常日志

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at Test.main(Test.java:29)
Caused by: MyException: 除数不能为0
	at Test.divde(Test.java:45)
	... 5 more

解决方案

通过异常日志我们可以看出来其实最终抛出的是java.lang.reflect.InvocationTargetException异常。通过源码注释我们也可以得出该结论。

/**
* @exception InvocationTargetException if the underlying method throws an exception.
*/
@CallerSensitive
    public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        return ma.invoke(obj, args);
    }

通过caused by可以看出该异常是由于自定义异常导致的。我们可以通过ex.getTargetException()获取目标异常。代码以及对应的日志如下:

public class Test {
  public static void main(String[] args) throws Exception {
    Test t = new Test();
    Class clz = t.getClass();
    Method addMethod = clz.getDeclaredMethod("divde", int.class, int.class);
    try {
      System.out.println(addMethod.invoke(new Test(), 1, 0));
    } catch (InvocationTargetException ex) {
      System.out.println("以下是InvocationTargetException异常:");
      ex.printStackTrace();
      System.out.println("以下是目标异常:");
      ex.getTargetException().printStackTrace();
    }
  }
  
  private double divde(int x, int y) {
    if (y == 0) {
      throw new MyException("除数不能为0");
    }
    return 1.0 * x / y;
  }
}
以下是InvocationTargetException异常:
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at Test.main(Test.java:31)
Caused by: MyException: 除数不能为0
	at Test.divde(Test.java:46)
	... 5 more
以下是目标异常:
MyException: 除数不能为0
	at Test.divde(Test.java:46)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at Test.main(Test.java:31)

你可能感兴趣的:(JAVA)