调用Method.invoke时获取java.lang.NullPointerException

我正在关注Java annotaitons的本教程,并实现了Test annotation,如图所示。 但是在运行代码时,我得到以下输出。

java.lang.NullPointerException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at TestAnnotationParser.parse(Demo.java:24) at Demo.main(Demo.java:51) Passed:0 Fail:1 

以下是我的代码。 有人能指出我错了吗?

 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @interface Test { Class expected(); } class TestAnnotationParser { public void parse(Class clazz) throws Exception { Method[] methods = clazz.getMethods(); int pass = 0; int fail = 0; for (Method method : methods) { if (method.isAnnotationPresent(Test.class)) { Test test = method.getAnnotation(Test.class); Class expected = test.expected(); try { method.invoke(null); pass++; } catch (Exception e) { if (Exception.class != expected) { e.printStackTrace(); fail++; } else { pass++; } } } } System.out.println("Passed:" + pass + " Fail:" + fail); } } class MyTest { @Test(expected = RuntimeException.class) public void testBlah() { } } public class Demo { public static void main(String[] args) { TestAnnotationParser parser = new TestAnnotationParser(); try { parser.parse(MyTest.class); } catch (Exception e) { e.printStackTrace(); } } } 

传递给invoke的参数必须是调用该方法的对象,除非该方法是static 。 你通过反思做了什么相当于:

 MyTest obj = null; obj.testBlah(); 

当然,有一个NPE。 要解决此问题,请传递要调用该方法的对象,或使该方法保持static

这是一种修复方法:

 public  void parse(Class clazz, T obj) throws Exception { Method[] methods = clazz.getMethods(); int pass = 0; int fail = 0; for (Method method : methods) { if (method.isAnnotationPresent(Test.class)) { Test test = method.getAnnotation(Test.class); Class expected = test.expected(); try { method.invoke(obj); pass++; } catch (Exception e) { if (Exception.class != expected) { e.printStackTrace(); fail++; } else { pass++; } } } } System.out.println("Passed:" + pass + " Fail:" + fail); } ... parser.parse(MyTest.class, new MyTest()); 

在ideone上演示 。

Method#invoke有你问题的答案:

 public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException 

抛出: NullPointerException – 如果指定的对象为null且方法是实例方法。

问题是您正在将null目标对象传递给method.invoke(object)方法。 目标对象不应为null,否则需要nullpointerexception。

调用方法有以下用法:

Method.invoke(targetObject, args1, args2, args3...); where args1, args2, args3 etc are argument to the method being invoked.

这个问题在这里:

 method.invoke(null); 

此方法的第一个参数是调用方法的对象。 这是类似这样的动态(reflection)等价物:

 Object foo = null; foo.toString(); 

当然我们希望这段代码给出一个NullPointerException因为foonull