1. 程式人生 > >java 反射使用 Class.getMethod 應註意

java 反射使用 Class.getMethod 應註意

com hashset arraylist 解決方案 string tro XML ret 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 應註意