确定类是否在Java中实现接口


91

我有一个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);
    }
}

Answers:


214

您应该使用isAssignableFrom

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

如果项目相同,则此方法有效。但是,如果您复制接口代码1:1,创建一个新项目和jar,然后尝试将该jar作为插件加载,则调用将返回false。比较名称,然后比较“有效”,就像Roddy发表的一样。但是我不知道如何以Java最终验证兼容性的方式检查这一点。顾名思义,这是一种肮脏的方法。当然,如果项目相同,则您的还可以。................也许我做错了:我为插件文件创建URLClassLoader实例,并像这样加载它。也许我应该尝试其他类加载器。
Dreamspace总裁

4
您遇到课程加载问题。如果您使用不同的类加载器两次加载同一类,则两个Class实例将不兼容。您可能会看到类似java.lang.ClassCastException: com.my.CustomClass cannot be cast to com.my.CustomClass或类似的莫名其妙的错误。
Flavio

到目前为止,我已经尝试了各种方法,最后发现我遇到的主要问题是:尽管我的插件和主项目中的接口相同,但它们不在同一位置,因此名称空间/地址是不同的。顺便说一句,我现在正在使用:myClassLoader = new URLClassLoader(new URL[] { candidateFile.toURI().toURL() }, LoadedPlugin.class.getClassLoader());classToLoad = Class.forName("com.blablabla.plugin.Main", true, myClassLoader);instance = (MyIntf) classToLoad.newInstance();就像一个魅力。
Dreamspace主席,

17

您可以使用以下功能获取所有已实现的接口

Class[] intfs = clazz.getInterfaces();

10

您可以使用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提到的那样,使用更简单,更清洁的方法。
jwj

是的,的确如此,尽管您的回答已被多次反对,我认为添加一些上下文将很有用。尽管使用isAssignableFrom可能更可取,但是在某些情况下,您可能需要通过查看名称来扫描类实现的接口列表。
jwj

这实际上是行不通的,只有在类直接实现接口的情况下,getInterfaces()才起作用,如果超类实现了接口,或者超级接口对其进行了扩展,则getInterfaces()不会返回该接口。您需要遍历所有超类和接口的树,以获取该类实现的所有接口。
詹姆斯·罗珀


1

您也可以将实例添加“ .class”

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

2
对于任何使用这种方法的人,请考虑Flavio的回答。请注意,此示例中的代码做了一些可能没有即时意义的事情:ClassUtils不是Java的一部分(它在Guava或Spring和其他框架中),Interface如上所用,该术语表示所测试的特定接口(即,在此情况下,它不是Java关键字),并且在retVal任何地方都没有解释或提及的目的。
jwj
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.