如何使用反射在.class(非对象)参数中调用java中的方法

时间:2018-02-16 13:42:31

标签: java reflection

我最近不得不使用反射来访问超类中的一些私有方法和字段。这就是我开始使用反射之前的样子:

            processSecondPassesOfType(PkDrivenByDefaultMapsIdSecondPass.class);
        processSecondPassesOfType(SetSimpleValueTypeSecondPass.class);
        processSecondPassesOfType(CopyIdentifierComponentSecondPass.class);
        processFkSecondPassInOrder();
        processSecondPassesOfType(CreateKeySecondPass.class);
        processSecondPassesOfType(SecondaryTableSecondPass.class);

现在我必须调用我通过反射获得的私有方法:

        Class<?> clazz = Class.forName("org.hibernate.cfg.Configuration");
        inSecondPass = true;
        Method m1 = clazz.getDeclaredMethod("processSecondPassesOfType", Class.class);
        m1.setAccessible(true);
        m1.invoke(PkDrivenByDefaultMapsIdSecondPass.class);

当我尝试运行此操作时,出现以下错误:

java.lang.IllegalArgumentException: object is not an instance of declaring class

那么如何使用反射调用非对象参数的方法?

2 个答案:

答案 0 :(得分:2)

除非这是静态方法,否则您需要在上调用的实例。

在普通代码中,您可以:

foo.bar(x, y, z); 

bar()上调用foo

通过反思,当你走的时候,逻辑就会以某种方式逆转:

handleToBar = ...
handleToBar.invoke(foo, x, y, ...

换句话说:你无法“在空气中”调用非静态方法。您必须提供一些要调用的对象。

当然,通常的免责声明:A)反思是“邪恶的”B)只有你必须使用它然后C)知道你在做什么和D)避免调用私人< / strong> - 这些是实施细节,可能会有变化。你只能在运行时找到它,因为A)反射是“邪恶的”。

答案 1 :(得分:1)

  

m1.invoke(PkDrivenByDefaultMapsIdSecondPass.class);

当方法为invokedjava.lang.reflect.Method.invoke()时,第一个参数是要在其上调用此特定方法的对象实例。 (如果方法是静态的,则第一个参数应为null。)后续参数是方法的参数。

因此,如果被调用的方法是静态的,则调用调用将是;

m.invoke(null, methodArguments);

如果被调用的方法不是静态的,则调用调用将是;

m.invoke(objectOnWhichMethodCalled, methodArguments);

如果基础方法抛出异常,它将被java.lang.reflect.InvocationTargetException包装。可以使用异常链接机制的InvocationTargetException.getCause()方法检索方法的原始异常。