我需要与大多数人想要处理的完全相反:我有一个带有className和methodName的StackTraceElement。当方法属于给定类实现的接口时,我需要一种方法来询问方法它起源于哪个接口。
我可以调用Class.forName(className)
,也可以调用clazz.getMethod(methodName)
,但是method.getDeclaringClass()
返回的是上述类的名称而不是其原始接口。我不想遍历所有类的接口来找到那个特定的方法,那实际上会使性能无效。
,
基本上它是一个遗留的广播机制。广播器类包含哈希映射,其中的键是接口,值是带有实现类的列表。广播器实现相同的接口,以便每个方法从hashmap中检索实现类,遍历它们并在每个实现类上调用相同的方法。
,
很抱歉在这里添加它,但是在注释中添加它有点太长了:
我的解决方案类似于Andreas所说的:
StackTraceElement invocationContext = Thread.currentThread().getStackTrace()[2];
Class<T> ifaceClass = null;
Method methodToInvoke = null;
for (Class iface : Class.forName(invocationContext.getClassName()).getInterfaces()) {
try {
methodToInvoke = iface.getMethod(invocationContext.getMethodName(), paramTypes);
ifaceClass = iface;
continue;
} catch (NoSuchMethodException e) {
System.err.println("Something got messed up.");
}
}
使用类似invocationContext
的结构可以创建一个拦截器,因此发送器只能包含带有空实现体的带注释的方法。
我有一个StackTraceElement与className和methodName。我需要一种方法来询问方法它起源于
中的哪个接口我不想遍历所有类的接口来找到那个特定的方法,那实际上会使性能无效。
我会首先检查遍历所有类接口在你的用例中是否真的对性能至关重要。通常,当您有堆栈跟踪元素时,您已经处于异常状态,此时性能可能不那么重要。然后,您可以使用Class.getInterfaces()
遍历接口并查询每个接口的声明方法,例如:
class MethodQuery {
private Set<Class<?>> result = new HashSet<>();
private String theMethodName;
private void traverse(Class<?> cls) {
for (Class<?> c : cls.getInterfaces()) {
for (Method m : c.getDeclaredMethods()) {
if (theMethodName.equals(m.getName())) {
result.add(c);
}
}
traverse(c);
}
}
public Set<Class<?>> getInterfacesForMethod(Class<?> cls, String methodName) {
result.clear();
theMethodName = methodName;
traverse(cls);
return result;
}
}
然后你可以像这样查询一个方法声明了哪个接口:
MethodQuery methodQuery = new MethodQuery();
Set<Class<?>> result =
methodQuery.getInterfacesForMethod(java.util.Vector.class, "addAll");
System.out.println(result);
结果:[interface java.util.Collection, interface java.util.List]
我无法想象为什么在性能敏感的情况下需要这样做,但是您可以缓存搜索结果。注意:同一个方法可以从多个接口实现同一个方法。
我不想遍历所有类的接口来找到那个特定的方法,那实际上会使性能无效。
我认为没有其他选择。
(但是呼应Peter Lawrey所说的,缓存会有帮助…如果性能很重要,一般应该避免反射。
注意:
- 一个给定的方法不能在任何接口中声明。
- 一个给定的方法可以在多个接口中声明,或者在通过多个路径继承的接口中声明。
你的方案必须考虑到这些事情,如果它是真正通用的。
保证一个方法只属于一个接口。
即便如此……