【问题标题】:How do I find the Java interface whose method is implemented in a given class?如何找到在给定类中实现其方法的 Java 接口?
【发布时间】:2013-04-17 22:11:22
【问题描述】:

我需要与大多数人想要处理的完全相反的东西:我有一个带有 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 的结构可以制作拦截器,因此发送器只能包含带有空实现主体的注释方法。

【问题讨论】:

  • 您是否尝试过Class.getInterfaces() 在您的用例中是否真的对性能至关重要?
  • 保证一种方法只属于一个接口。
  • 安德烈亚斯,您能否添加您的评论作为答案?我最终选择了 Class.getInterfaces(),似乎成功了。

标签: java reflection methods interface


【解决方案1】:

我有一个带有 className 和 methodName 的 StackTraceElement。
我需要一种方法,我可以询问它源自哪个接口的方法
我不想遍历所有类的接口来找到那个特定的方法,这实际上会使性能无效。

我会首先检查在您的用例中迭代所有类接口是否真的对性能至关重要。通常,当您拥有堆栈跟踪元素时,您已经处于异常状态,性能可能并不那么关键。然后您可以使用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]

【讨论】:

    【解决方案2】:

    我无法想象为什么您会在性能敏感的情况下需要它,但您可以缓存搜索结果。注意:同一个方法可能会从多个接口实现一个方法。

    【讨论】:

      【解决方案3】:

      我不想遍历所有类的接口来找到那个特定的方法,这实际上会使性能无效。

      我认为没有其他选择。

      (但是为了呼应 Peter Lawrey 的说法,缓存会有所帮助......如果性能很重要,一般应该避免反射。)

      另请注意:

      • 给定方法可能未在任何接口中声明。
      • 在多个接口中或在通过多个路径继承的接口中声明给定的方法。

      如果要真正通用,您的方案必须考虑这些因素。


      保证一个方法只属于一个接口。

      即便如此……

      【讨论】:

      • 一个给定的方法在一个且只有一个接口中声明,但是该接口由多个类实现。一个类已经包含一个 HashMap 和其余的实现类,其中接口是键。这就是我需要接口的原因,因此我可以将每个方法调用广播到所有其他实现类。
      猜你喜欢
      • 2010-10-16
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多