【问题标题】:Java Reflection NoSuchMethodException when referencing a method in same class引用同一类中的方法时的Java反射NoSuchMethodException
【发布时间】:2017-12-03 07:49:26
【问题描述】:

我在尝试对同一类中的方法调用 getMethod 时遇到 NoSuchMethodException,而从哈希映射中提取的字符串名称没有参数。任何建议,或仅在给定方法的字符串名称的情况下调用同一类中的方法的另一种方法? 获取方法的调用在这里:

if (testChoices.containsKey(K)) {
        String method = testChoices.get(K);
        System.out.println(method);

        try {
            java.lang.reflect.Method m = TST.getClass().getMethod(method);
            m.invoke(testChoices.getClass());
        } catch (NoSuchMethodException e1) {
            // TODO Auto-generated catch block
            System.out.println("No method found");
            e1.printStackTrace();
        } catch (SecurityException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();


        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

我试图调用的方法之一在这里:

private static void testgetDomainLic() throws IOException {

被调用的地图条目在这里:

testChoices.put(1, "testgetDomainLic");

【问题讨论】:

  • 静态方法testgetDomainLic()是在TST类中定义的,还是在它的超接口中定义的?
  • TST 只是 testgetDomainLic() 所在类的一个实例。
  • 我改成用 Class.forName 调用直接定义的类,还是找不到方法。

标签: java reflection invoke nosuchmethod


【解决方案1】:

我认为在您的情况下,您可以将getMethod 更改为getDeclaredMethodgetMethod 只返回公共方法。

这里的问题是它们实际上具有不同的语义other,而不是它们是否返回非公共方法。 getDeclaredMethod 仅包含已声明而非继承的方法。

例如:

class Foo { protected void m() {} }
class Bar extends Foo {}
Foo actuallyBar = new Bar();
// This will throw NoSuchMethodException
// because m() is declared by Foo, not Bar:
actuallyBar.getClass().getDeclaredMethod("m");

在最坏的情况下,你必须遍历所有声明的方法,如下所示:

Class<?> c = obj.getClass();
do {
    for (Method m : c.getDeclaredMethods())
        if (isAMatch(m))
            return m;
} while ((c = c.getSuperclass()) != null);

或者考虑接口(主要是因为它们现在可以声明静态方法):

List<Class<?>> classes = new ArrayList<>();
for (Class<?> c = obj.getClass(); c != null; c = c.getSuperclass())
    classes.add(c);
Collections.addAll(classes, obj.getClass().getInterfaces());
Method m = classes.stream()
                  .map(Class::getDeclaredMethods)
                  .flatMap(Arrays::stream)
                  .filter(this::isAMatch)
                  .findFirst()
                  .orElse(null);

附带说明一下,您可能不需要调用m.setAccessible(true),因为您是在声明它的类中调用它。不过,在其他情况下,这是必要的。

【讨论】:

    【解决方案2】:

    我不是专家,但请尝试更改您的方法,使其不是私密的。

    可以通过反射调用私有方法,但有额外的步骤。见Any way to Invoke a private method?

    【讨论】:

    • OP 收到 NoSuchMethodException。问题在于getMethod()——而不是invoke()
    • 另外,我已经尝试删除 Private 但它仍然给出相同的错误
    • 好的。所以我正在解决他们尚未解决的问题!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    相关资源
    最近更新 更多