14

Javaアノテーションに関するこのチュートリアルに従っており、そこに示されているようにテストアノテーションを実装しています。しかし、コードを実行すると、次の出力が得られます。

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();
        }
    }
}
4

4 に答える 4

17

渡すパラメータinvokeは、メソッドが呼び出されるオブジェクトでなければなりませんstatic。リフレクションを通じて行ったことは、これと同等です。

MyTest obj = null;
obj.testBlah();

当然、NPE があります。この問題を解決するには、メソッドを呼び出すオブジェクトを渡すか、メソッドを作成しstaticます。

修正する方法の 1 つを次に示します。

public <T> void parse(Class<T> 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 のデモ

于 2013-09-14T13:39:28.680 に答える
3

Method#invokeには、質問に対する答えがあります。

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

例外: NullPointerException- 指定されたオブジェクトが null で、メソッドがインスタンス メソッドの場合。

于 2013-09-14T13:43:55.393 に答える
1

この問題はここにあります:

method.invoke(null);

このメソッドの最初のパラメーターは、メソッドを呼び出すオブジェクトです。これは、次のようなものと同等の動的 (反射) です。

Object foo = null;
foo.toString();

もちろん、このコードはNullPointerExceptionなぜならfooisを与えると予想しますnull

于 2013-09-14T13:39:38.590 に答える
1

method.invoke(object)問題は、null ターゲット オブジェクトをメソッドに渡していることです。ターゲット オブジェクトは null であってはなりません。そうでない場合、nullpointerexception が予想されます。

invoke メソッドには以下の使用法があります。

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

于 2013-09-14T13:42:26.697 に答える