java 反射使用 Class.getMethod 应注意

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 反射使用 Class.getMethod 应注意相关的知识,希望对你有一定的参考价值。

java 反射使用 Class.getMethod 应注意 记录下

Method method= clazz.getMethod(setMethodName,propertiesClass);
如果使用该方法 会不能获取以多态方式传入的参数
会抛异常 java.lang.NoSuchMethodException
比如:

public class Student {

private String name;

private int age;

private List list = new ArrayList();

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public List<Object> getList() {
    return list;
}

public void setList(List<Object> list) {
    this.list = list;
}

}

 public static void main(String[] args) {
    try {
        Class<?> clazz= Class.forName(Student.class.getTypeName());
        List list = new ArrayList();
        clazz.getMethod("setList",list.getClass());

    } catch (ClassNotFoundException | NoSuchMethodException e) {
        e.printStackTrace();
    }

}

    此时会抛异常:
    java.lang.NoSuchMethodException: com.jcb.xml.model.Student.setList(java.util.ArrayList)

    解决方案:

    /**
 * 获取只有一个参数的对应方法
 * @param className
 * @param methodName
 * @return
 */
private Method getMethod(String className,String methodName,Class<?> propertiesClass){

    Method[] methods=getMethods(className);
    for (Method method : methods) {
        if(method.getName().equals(methodName)){
            if(method.getParameterCount() == 1){
                //该函数的参数类型和传入参数类型相同
                if(method.getParameterTypes()[0].getTypeName().equals(propertiesClass.getTypeName())){
                    return method;
                    //该函数的参数类型是传入参数类型的父类
                }else if(method.getParameterTypes()[0].getTypeName().equals(propertiesClass.getSuperclass().getTypeName())){
                    return method;
                }else
                {
                    Set<String> superClassAndSuperInterfaceList= this.getAllSuperClassAndSuperInterface(propertiesClass);
                    //如果传入参数类型是参数类型的子类 也返回改函数
                    if(superClassAndSuperInterfaceList.contains(method.getParameterTypes()[0].getTypeName()))
                        return method;

                }
            }
        }
    }
    return  null;
}

    /**
 * 获取所有父类类型和父类接口类型
 * @param clazz
 * @return
 */
private Set<String> getAllSuperClassAndSuperInterface(Class<?> clazz){
    Set<String> superClassAndSuperInterfaceList = new HashSet<>();
    getAllSupersClasss(superClassAndSuperInterfaceList,clazz);
    getAllSuperInterfaces(superClassAndSuperInterfaceList,clazz);
    return superClassAndSuperInterfaceList;
}

/**
 * 递归获取所父类 类型
 * @param parentClassList
 * @param clazz
 */
private Set<String> getAllSupersClasss(Set<String> parentClassList,Class<?> clazz){
    parentClassList.add(clazz.getSuperclass().getName());
    if(Object.class.getTypeName()!=clazz.getSuperclass().getTypeName()){
        //父类也可能实现接口
        getAllSuperInterfaces(parentClassList,clazz.getSuperclass());
        //递归查询父类
        getAllSupersClasss(parentClassList,clazz.getSuperclass());
    }
    return parentClassList;
}

/**
 * 递归获取父类接口
 * @param parentInterfaceList
 * @param clazz
 */
private Set<String> getAllSuperInterfaces(Set<String> parentInterfaceList,Class<?> clazz){
    for (Class<?> aClass : clazz.getInterfaces()) {
        parentInterfaceList.add(aClass.getTypeName());
        //递归查询实现接口
        getAllSuperInterfaces(parentInterfaceList,aClass);
    }
    return parentInterfaceList;
}

    使用该getMethod 代替反射 Class.getMethod 方法 就可以  

    暂时想到的就是这一个解决方案

    多参数函数类似

以上是关于java 反射使用 Class.getMethod 应注意的主要内容,如果未能解决你的问题,请参考以下文章

一个事半功倍的 Java 反射库

为啥这个 Java 方法只能使用反射?

反射之getField()与getDeclaredField()的区别

反射之Method如何获取字节码对象中的方法

有一个反射的小程序引出的问题

在 Java 和 C 中在运行时调用名为“string”的方法