我想使用具有不同参数数量的函数。问题是我不知道每个函数的参数数量,也不知道函数的名称,因为它们存储在一个数组中。我只知道班级名称,但不想使用getDeclaredMethods
,因为它会增加搜索时间。有没有办法为每个函数获取参数类型?如何使用反射获取参数类型?
8
A
回答
4
当我必须查找方法时,我通常会做的是从查询中生成一个缓存键,并将该缓存键的搜索结果保存在地图中。
例子:
我知道方法参数Boolean.TRUE
,Arrays.asList("foo","bar","baz")
和BigInteger.valueOf(77777l)
我的类包含与签名的方法
public foo(boolean, Collection, Number)
有没有办法,我可以将参数直接映射参数类型,因为我只是不知道哪个超类或接口是参数类型,如下表所示:
这些对每一个是兼容的,但是没有办法找到兼容的方法没有定义的比较方法,像这样:
// determine whether a method's parameter types are compatible
// with my arg array
public static boolean isCompatible(final Method method,
final Object[] params) throws Exception{
final Class<?>[] parameterTypes = method.getParameterTypes();
if(params.length != parameterTypes.length){
return false;
}
for(int i = 0; i < params.length; i++){
final Object object = params[i];
final Class<?> paramType = parameterTypes[i];
if(!isCompatible(object, paramType)){
return false;
}
}
return true;
}
// determine whether a single object is compatible with
// a single parameter type
// careful: the object may be null
private static boolean isCompatible(final Object object,
final Class<?> paramType) throws Exception{
if(object == null){
// primitive parameters are the only parameters
// that can't handle a null object
return !paramType.isPrimitive();
}
// handles same type, super types and implemented interfaces
if(paramType.isInstance(object)){
return true;
}
// special case: the arg may be the Object wrapper for the
// primitive parameter type
if(paramType.isPrimitive()){
return isWrapperTypeOf(object.getClass(), paramType);
}
return false;
}
/*
awful hack, can be made much more elegant using Guava:
return Primitives.unwrap(candidate).equals(primitiveType);
*/
private static boolean isWrapperTypeOf(final Class<?> candidate,
final Class<?> primitiveType) throws Exception{
try{
return !candidate.isPrimitive()
&& candidate
.getDeclaredField("TYPE")
.get(null)
.equals(primitiveType);
} catch(final NoSuchFieldException e){
return false;
} catch(final Exception e){
throw e;
}
}
所以我会做的是有一个方法缓存:
private static final Map<String, Set<Method>> methodCache;
和添加的查找方法是这样的:
public static Set<Method> getMatchingMethods(final Class<?> clazz,
final Object[] args) throws Exception{
final String cacheKey = toCacheKey(clazz, args);
Set<Method> methods = methodCache.get(cacheKey);
if(methods == null){
final Set<Method> tmpMethods = new HashSet<Method>();
for(final Method candidate : clazz.getDeclaredMethods()){
if(isCompatible(candidate, args)){
tmpMethods.add(candidate);
}
}
methods = Collections.unmodifiableSet(tmpMethods);
methodCache.put(cacheKey, methods);
}
return methods;
}
private static String toCacheKey(final Class<?> clazz, final Object[] args){
final StringBuilder sb = new StringBuilder(clazz.getName());
for(final Object obj : args){
sb.append('-').append(
obj == null ? "null" : obj.getClass().getName());
}
return sb.toString();
}
这样,随后的查找将比第一个查找花费更少的时间(对于相同类型的参数)。
当然,因为Class.getDeclaredMethods()
在内部使用缓存,所以问题是我的缓存是否改善了性能。它基本上是一个什么样的速度更快问题:
- 生成缓存键和查询一个HashMap或
- 遍历所有的方法和查询参数兼容性
我的猜测:大班(许多方法),第一种方法将获胜,否则第二种方法将
相关问题
- 1. 如何使用java反射获取类型参数值?
- 2. 获取参数使用反射的动态方法的类型
- 3. 使用scala获取方法参数类型2.10反射API
- 4. 使用反射获取类型
- 5. 获取容器类型使用反射
- 6. 使用反射获取MemberInfo的类型
- 7. 如何通过反射获得通用参数的类型
- 8. dart,如何使用反射获得泛型类型的方法参数?
- 9. 如何使用Java反射从ParameterizedType获取GenericDeclaration的类型?
- 10. 如何使用反射来获取字段的类型?
- 11. 如何使用Java反射获取javax.xml.ws.Holder中的实际类型?
- 12. C#反射 - 投射参数到类型
- 13. 如何查找Action的参数类型(使用反射)?
- 14. 如何确定使用反射基类的泛型参数
- 15. 我可以使用反射类型作为类型参数吗?
- 16. PHP反射 - 获取方法参数类型为字符串
- 17. 如何使用Java反射获取参数名称
- 18. 如何获取使用反射的方法的参数
- 19. 使用反射获取所有Integer数据类型字段
- 20. Java反射:从实现类获取泛型接口的类型参数
- 21. Java:在嵌套参数化类型中获取内部类型(反射)
- 22. 使用反射获取参数的参数
- 23. Php在Hack中使用反射获取泛型类型
- 24. ObservableArrayList:如何通过反射获取通用类型?
- 25. 从反射获取实际类型fieldInfo
- 26. 反射获取FieldInfo对象的类型?
- 27. 泛型反射,如何获取列表?
- 28. 使用反射来获取静态类
- 29. 使用反射获取类变量值
- 30. 使用反射来获取类描述
*,因为它们存储在一个数组*谁是'他们'?方法或参数?请展示一些代码来说明 – 2011-02-11 09:52:05