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 方法 就可以 多参数函数类似
第二种方法 更清晰 包含多参数函数
/**
获取参数所对应的函数
@param className
@param argsClass
@return
*/
private Method getMethod(String className, String methodName,Class<?>[] argsClass){
Method[] methods=getMethods(className);
for (Method method : methods) {
if(method.getName().equals(methodName)) {
if (method.getParameterTypes().length == argsClass.length) {
if (checkArgsType(method.getParameterTypes(), argsClass)) {
return method;
}
} else {
continue;
}
}
}return null;
}
/**
@param sourceArgsClass 函数的参数类型
@param argsClass 传入函数的参数类型
@return
*/
private boolean checkArgsType(Class<?>[] sourceArgsClass,Class<?>[] argsClass){for (int i =0;i< sourceArgsClass.length;i++) { //aClass.isAssignableFrom(bClass) 判断a是否是b的父类或则父接口 if(!sourceArgsClass[i].isAssignableFrom(argsClass[i])) return false;}return true;
}