【问题标题】:Determine if a Class implements a interface in Java确定一个类是否在 Java 中实现了一个接口
【发布时间】:2012-08-22 03:07:31
【问题描述】:

我有一个Class 对象。我想确定Class 对象所代表的类型是否实现了特定的接口。我想知道这是如何实现的?

我有以下代码。基本上它所做的是获取指定包中所有类的数组。然后我想遍历数组并将实现接口的 Class 对象添加到我的地图中。问题是isInstance() 将对象作为参数。我无法实例化接口。所以我对此有点不知所措。有什么想法吗?

Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
    if(clazz.isInstance(/*Some object*/)) //Need something in this if statement
    {
        retVal.put(clazz.getSimpleName(), clazz);
    }
}

【问题讨论】:

    标签: java reflection


    【解决方案1】:

    你应该使用isAssignableFrom:

    if (YourInterface.class.isAssignableFrom(clazz)) {
        ...
    }
    

    【讨论】:

    • 如果项目相同,则此方法有效。但是如果你 1:1 复制接口代码,新建一个项目和 jar,然后尝试将那个 jar 作为插件加载,调用将返回 false。按名称比较然后“工作”,就像罗迪发布的那样。但我不知道如何以 Java 最终验证兼容性的方式检查这一点。顾名思义,这是一种肮脏的方法。当然,如果项目相同,您的也可以。 ............. 也许我做错了:我为插件文件创建了一个 URLClassLoader 实例并像这样加载它。也许我应该尝试不同的类加载器。
    • 您遇到了类加载问题。如果你用不同的类加载器加载同一个类两次,这两个Class 实例将不兼容。您可能会看到像 java.lang.ClassCastException: com.my.CustomClass cannot be cast to com.my.CustomClass 这样的错误或类似的莫名其妙的东西。
    • 我已经尝试了各种方法,最后发现我遇到的主要问题是这样的:虽然我的插件和主项目中的界面是相同,它们不在同一个地方,所以命名空间/地址是不同的。顺便说一句,我现在正在使用:myClassLoader = new URLClassLoader(new URL[] { candidateFile.toURI().toURL() }, LoadedPlugin.class.getClassLoader());classToLoad = Class.forName("com.blablabla.plugin.Main", true, myClassLoader);instance = (MyIntf) classToLoad.newInstance(); 就像一个魅力。
    【解决方案2】:

    你可以使用下面的函数来获取所有实现的接口

    Class[] intfs = clazz.getInterfaces();
    

    【讨论】:

      【解决方案3】:

      你可以使用class.getInterfaces(),然后查看接口类是否在里面。

      Class someInterface; // the interface you want to check for 
      Class x; // 
      Class[] interfaces = x.getInterfaces();
      
      for (Class i : interfaces) {
          if (i.toString().equals(someInterface.toString()) {
              // if this is true, the class implements the interface you're looking for
          }
      }
      

      【讨论】:

      • 这种方法在技术上可行,但更简单、更简洁的方法是使用 isAssignableFrom,正如 Flavio 提到的那样。
      • 是的,确实如此,尽管您的答案已被多次投票,我认为添加一些上下文会很有用。虽然使用isAssignableFrom 可能更可取,但在某些情况下,您可能需要通过查看名称来扫描类实现的接口列表。
      • 这实际上是行不通的,getInterfaces() 仅在类直接实现接口的情况下才有效,如果超类实现了接口,或者超接口扩展了它,则该接口不会被返回获取接口()。需要遍历所有超类和接口的树,才能得到该类实现的所有接口。
      • 这不是问题。
      【解决方案4】:

      也可以设置实例添加“.class”

      Class[] classes = ClassUtils.getClasses(handlersPackage);
      for(Class clazz : classes)
      {
          if(Interface.class.isAssignableFrom(clazz))
          {
              retVal.put(clazz.getSimpleName(), clazz);
          }
      }
      

      【讨论】:

      • 对于任何研究这种方法的人,请考虑 Flavio 的回答。请注意,此示例中的代码做了一些可能没有立即意义的事情:ClassUtils 不是 Java 的一部分(它在 Guava 或 Spring 和其他框架中),上面使用的术语 Interface 是指正在测试的特定接口(即,在此上下文中它不是 Java 关键字),并且在任何地方都没有解释或提及 retVal 的用途。
      猜你喜欢
      • 2012-05-08
      • 1970-01-01
      • 2013-02-14
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 2010-10-04
      相关资源
      最近更新 更多