概述

在这个教程中,我们将探讨几种方法来确定一个对象或类是否实现了特定的接口。

2. 使用Java反射API

Java反射API提供了多种方式来检查一个对象或类是否实现了接口。使用这个API可以避免在项目中添加第三方库。

2.1. 数据模型

Java运行环境(JRE)提供了一些方法来获取类实现的接口。首先,我们定义一个模型,包含一些接口和类:

  • 定义一个接口MasterInterface,以及两个扩展它的子接口:


    接口示例

  • 类方面,有一个实现MasterInterface的类,以及两个分别实现ChildInterface1ChildInterface2的子类:


    类示例

以下是我们的模型代码:

public interface MasterInterface {}

public interface ChildInterface1 extends MasterInterface {}

public interface ChildInterface2 extends MasterInterface {}

public class MasterClass implements MasterInterface {}

public class ChildClass1 implements ChildInterface1 {}

public class ChildClass2 implements ChildInterface2 {}

2.2. getInterfaces() 方法

Java API在Class对象上提供了getInterfaces()方法,用于获取一个类实现的所有接口。我们可以用以下代码获取一个类的所有直接实现接口:

List<Class<?>> interfaces = Arrays.asList(childClass2.getClass().getInterfaces());

assertEquals(1, interfaces.size());
assertTrue(interfaces.contains(ChildInterface2.class));

注意:这种方法只返回直接实现的接口,不检测接口的继承关系。

如果我们想获取完整的继承树,需要递归遍历实现的接口,直到找到根接口:

static Set<Class<?>> getAllExtendedOrImplementedInterfacesRecursively(Class<?> clazz) {

    Set<Class<?>> res = new HashSet<Class<?>>();
    Class<?>[] interfaces = clazz.getInterfaces();

    if (interfaces.length > 0) {
        res.addAll(Arrays.asList(interfaces));

        for (Class<?> interfaze : interfaces) {
            res.addAll(getAllExtendedOrImplementedInterfacesRecursively(interfaze));
        }
    }

    return res;
}

执行后,我们可以验证我们在Set中确实获取到了MasterInterface

assertTrue(interfaces.contains(ChildInterface2.class));
assertTrue(interfaces.contains(MasterInterface.class));

现在,我们有能力检查模型中的对象是否实现了特定的接口。

2.3. isAssignableFrom() 方法

前面的方法较为繁琐,Java API提供了更简洁的方法来检查Object是否实现了接口,即使用Class对象的isAssignableFrom()方法。

这个方法如果对象继承了指定的接口,即使不是直接实现,也会返回true

ChildClass2 childClass2 = new ChildClass2();
assertTrue(MasterInterface.class.isAssignableFrom(childClass2.getClass()));

2.4. isInstance() 方法

Class对象还提供了isInstance()方法,它会返回提供的对象是否实现了接口:

assertTrue(MasterInterface.class.isInstance(childClass2));

2.5. instanceOf 运算符

最后一种检查方法是使用instanceOf运算符,它同样适用于接口:

assertTrue(childClass2 instanceof MasterInterface);

3. 使用Apache Commons库

Apache Commons Lang库提供了几乎所有的实用类。ClassUtils类能够列出一个类实现的所有接口。

首先,我们需要在pom.xml中添加Maven中央仓库的依赖:

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.12.0</version>
</dependency>

这与使用getInterfaces()方法类似,但只需要一行代码:

List<Class<?>> allSuperInterfaces = ClassUtils.getAllInterfaces(childClass2.getClass());

这将递归返回所有实现的接口:

assertTrue(allSuperInterfaces.contains(ChildInterface2.class)); assertTrue(allSuperInterfaces.contains(MasterInterface.class));

4. 使用Reflections库

Reflections库是一个第三方库,它可以扫描我们的对象并允许我们针对收集到的元数据运行查询。

首先,我们需要在pom.xml中添加Maven中央仓库的依赖:

<dependency>
  <groupId>org.reflections</groupId>
  <artifactId>reflections</artifactId>
  <version>0.10.2</version>
</dependency>

在运行查询之前,库需要先收集数据,因此需要初始化:

Reflections reflections = new Reflections("com.baeldung.checkInterface");

这个操作会扫描整个提供的类路径,可能需要一段时间才能完成。通常可以在应用启动时进行,以便后续查询能顺利进行。

然后,我们可以获取一个类实现的接口列表:

Set<Class<?>> classes = reflections.get(ReflectionUtils.Interfaces.of(ChildClass2.class));

5. 总结

本文介绍了检查类是否实现特定接口的不同方法。根据应用程序的需求,我们可以选择使用标准的Java反射API,或者如果需要更强大的功能,可以依赖第三方库。

如需查看完整代码,请访问GitHub