我可以通过Java反射获得方法正在实现的接口吗?

时间:2017-08-17 07:39:06

标签: java reflection interface

我正在编写消息传递组件,出于某些原因,我需要找出哪些类的方法可以被消息传递组件调用。在其他标准中,这些方法需要实现特定的接口。如何通过反射找出这些方法?我有权访问该类,但我不能依赖于方法名称。类中可能有类似的方法具有相同的名称但不实现所需的(或任何)接口。例如:

interface A
{
   long set(Object object)
}

class B implements A
{
   public long set(Object object)
   {
      System.out.println("I am the method they are looking for!");
   }

   public void set(int i, int j)
   {
      System.out.println("I am not the qualifying method!");
   }
}

所以,简而言之,我想通过反射而不是第二种方法找到第一种方法。这在Java中是否可行?

2 个答案:

答案 0 :(得分:-1)

您可以使用以下命令建立声明方法的接口列表:

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class B extends D implements A {

    public Long set(Object object) {
        System.out.println("I am the method they are looking for!");
        return (long) 0;
    }

    public void set(int i, int j) {
        System.out.println("I am not the qualifying method!");
    }

    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        Method methodToCheck = B.class.getDeclaredMethod("set", Object.class);
        List<Class<?>> declaringInterfaces = searchForDeclaringInterfaces(methodToCheck, B.class);
        System.out.println("The method " + methodToCheck + " is declared in these interfaces:");
        for (Class<?> c : declaringInterfaces) {
            System.out.println(c.getCanonicalName());
        }

    }

    public static List<Class<?>> searchForDeclaringInterfaces(Method methodToCheck, Class<?> clazz)
            throws NoSuchMethodException {
        if (clazz == null) {
            return Collections.EMPTY_LIST;
        }
        LinkedList<Class<?>> declaringInterfaces = new LinkedList<>();
        for (Class<?> c : clazz.getInterfaces()) {
            Method methodFromInterface = searchMethods(c.getDeclaredMethods(), methodToCheck.getName(),
                    methodToCheck.getParameterTypes());
            if (methodFromInterface != null) {
                declaringInterfaces.add(c);
            }
        }
        declaringInterfaces.addAll(searchForDeclaringInterfaces(methodToCheck, clazz.getSuperclass()));
        return declaringInterfaces;
    }

    private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) {
        Method res = null;
        String internedName = name.intern();
        for (int i = 0; i < methods.length; i++) {
            Method m = methods[i];
            if (m.getName() == internedName && arrayContentsEq(parameterTypes, m.getParameterTypes())
                    && (res == null || res.getReturnType().isAssignableFrom(m.getReturnType())))
                res = m;
        }

        return res;
    }

    private static boolean arrayContentsEq(Object[] a1, Object[] a2) {
        if (a1 == null) {
            return a2 == null || a2.length == 0;
        }

        if (a2 == null) {
            return a1.length == 0;
        }

        if (a1.length != a2.length) {
            return false;
        }

        for (int i = 0; i < a1.length; i++) {
            if (a1[i] != a2[i]) {
                return false;
            }
        }

        return true;
    }
}

interface A extends C {
    public Number set(Object object);
}

interface C {
    Number set(Object object);
}

class D implements C {

    @Override
    public Number set(Object object) {
        return null;
    }

}

这将打印:

The method public java.lang.Long B.set(java.lang.Object) is declared in these interfaces:
A
C

它打印B类树中所有接口并声明此方法。

答案 1 :(得分:-1)

是......而且没有。

遍历类的超类和接口的DAG,为每个类调用getDeclaredMethods()以获取在接口中声明的一组Method个对象。然后查找该集与该类本身的声明方法集之间的匹配。

一个问题是类中的给定方法可以实现多个接口声明的抽象方法。

第二个问题是决定匹配语义的正确(对于你的应用程序!)方法并实现它。 (请注意,您的示例只是一个示例。它没有指定任何语义。)