java获取接口所有实现类_Java反射获取某个接口的所有实现类

还是一样,我在写日志框架时遇到的问题,获取一个接口的所有实现类,但是我发现反射API中并没有或者实现类的API。无奈,只能自己动了。

老样子,先上代码,后上教程:

/**

* 获取一个接口的所有实现类

*

* @param target

* @return

*/

public static ArrayList> getInterfaceImpls(Class> target) {

ArrayList> subclassaes = Lists.newArrayList();

try {

// 判断class对象是否是一个接口

if (target.isInterface()) {

@NotNull

String basePackage = target.getClassLoader().getResource("").getPath();

File[] files = new File(basePackage).listFiles();

// 存放class路径的list

ArrayList classpaths = Lists.newArrayList();

for (File file : files) {

// 扫描项目编译后的所有类

if (file.isDirectory()) {

listPackages(file.getName(), classpaths);

}

}

// 获取所有类,然后判断是否是 target 接口的实现类

for (String classpath : classpaths) {

Class> classObject = Class.forName(classpath);

if (classObject.getSuperclass() == null) continue; // 判断该对象的父类是否为null

Set> interfaces = new HashSet<>(Arrays.asList(classObject.getInterfaces()));

if (interfaces.contains(target)) {

subclasses.add(Class.forName(classObject.getName()));

}

}

} else {

throw new ParamException("Class对象不是一个interface");

}

} catch (Throwable e) {

e.printStackTrace();

}

return subclasses;

}

/**

* 获取项目编译后的所有的.class的字节码文件

* 这么做的目的是为了让 Class.forName() 可以加载类

*

* @param basePackage 默认包名

* @param classes 存放字节码文件路径的集合

* @return

*/

public static void listPackages(String basePackage, List classes) {

URL url = SophonUtils.class.getClassLoader()

.getResource("./" + basePackage.replaceAll("\\.", "/"));

File directory = new File(url.getFile());

for (File file : directory.listFiles()) {

// 如果是一个目录就继续往下读取(递归调用)

if (file.isDirectory()) {

listPackages(basePackage + "." + file.getName(), classes);

} else {

// 如果不是一个目录,判断是不是以.class结尾的文件,如果不是则不作处理

String classpath = file.getName();

if (".class".equals(classpath.substring(classpath.length() - ".class".length()))) {

classes.add(basePackage + "." + classpath.replaceAll(".class", ""));

}

}

}

}

代码演示:

使用方法非常简单,你只需要调用getInterfaceImpls()方法即可,listPackages()方法是个辅助。

//

// getInstanceImpls()返回一个Class>对象数组

// 这个数组中包含的数据就是SophonInit接口的子类

//

ArrayList> subclass = getInterfaceImpls(SophonInit.class);

ps:值的注意的地方是,这个方法只能获取项目中自己定义的接口,不能获取到JDK或者是其他Jar包中的接口,因为这个工具的原理就是扫描编译后的classes目录

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
获取某个接口下所有的实现类,可以使用反射机制来实现。以下是一个示例代码: ```java import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; public class InterfaceImplFinder { public static List<Class<?>> getImplementations(Class<?> interfaceClass) { List<Class<?>> implementations = new ArrayList<>(); // 获取当前ClassLoader加载的所有类 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); try { Class<?>[] allClasses = getAllClasses(classLoader); // 遍历所有类,找出实现了指定接口的类 for (Class<?> clazz : allClasses) { if (interfaceClass.isAssignableFrom(clazz) && !Modifier.isAbstract(clazz.getModifiers())) { implementations.add(clazz); } } } catch (Exception e) { e.printStackTrace(); } return implementations; } private static Class<?>[] getAllClasses(ClassLoader classLoader) throws Exception { // 获取ClassLoader中的类加载器字段 Class<?> classLoaderClass = classLoader.getClass(); while (classLoaderClass != ClassLoader.class) { classLoaderClass = classLoaderClass.getSuperclass(); } java.lang.reflect.Field classesField = classLoaderClass.getDeclaredField("classes"); classesField.setAccessible(true); // 通过反射获取ClassLoader中的所有类 Vector<Class<?>> classes = (Vector<Class<?>>) classesField.get(classLoader); return classes.toArray(new Class[classes.size()]); } public static void main(String[] args) { List<Class<?>> implementations = getImplementations(Runnable.class); for (Class<?> clazz : implementations) { System.out.println(clazz.getName()); } } } ``` 在上面的示例代码中,`getImplementations` 方法接受一个接口的 `Class` 对象作为参数,然后使用反射遍历所有类,找出实现了该接口且非抽象的类,并将它们添加到一个列表中返回。你可以将你想要获取实现类的接口类替换 `Runnable.class`,然后运行 `main` 方法查看结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值