Java如何扫描指定包下所有类?

Java如何扫描指定包下所有类?

复制代码
Java8、jdk8、idea、反射、class

背景

每次写算法题时,总觉得测试代码写起来又没营养又很麻烦,即便是借助junit测试框架也很麻烦,太重了。

正好在学习spring过程中接触到注解,研究其原理时了解到反射,借由注解和反射,应该可以自定义一个轻量级的测试框架。

预期分为两篇,一篇介绍 类文件的扫描和反射,一篇介绍 按照注解执行类中的方法

本文方法部分借鉴于这篇博客,有所改动。

解决方案

  1. 获取包名 Main.class.getPackage().getName() (我的启动类是"Main")
  2. 利用包名获取资源路径列表 Thread.currentThread().getContextClassLoader().getResources(pkgName)
    返回值类型 Enumeration<URL>
  3. 遍历资源路径(上一步返回值) resources.nextElement().getFile()
  4. 利用资源路径新建文件对象 new File(pkgResourcePathName)
  5. 利用 file.isFile() 检查文件对象是文件还是目录,文件直接添加进文件列表(注意查看文件名后缀,筛选".class"文件)
  6. 若文件对象是目录,使用 file.listFiles() 依次列举其内对象,回到第5步,递归判断(目录结构层次不深的可以采用此法,目录深的可以利用队列或栈手动操作)
  7. 文件类型的对象,可以使用Class.forName(fileName)获取其对应 Class 对象,文件名需要处理成类似 com.example.main.Main 形式

代码示例:

java 复制代码
// Main.java:

private static List<File> classFileList = new ArrayList<>();

private static String rootPackageName = "main";
// 控制是否扫描主类包下和主类同级的类文件
private static boolean scanMainPackageClass = false;

 /**
 * 将文件对象转换为 Class 对象
 */
 public static Class convertClass(File file) throws Exception {
     String path = file.getPath();
     String className = path.substring(path.indexOf(rootPackageName))
             .replaceAll("\\\\", ".")
             .replaceAll("\\.class", "");
     return Class.forName(className);
 }

 /**
  * 默认从主类所在包开始扫描class文件
  */
 public static void loadClassFiles() throws Exception {
     loadClassFiles(Main.class);
 }

 /**
  * 从指定类所在包开始,扫描class文件
  */
 public static void loadClassFiles(Class cls) throws Exception {
     Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(cls.getPackage().getName());
     if (!resources.hasMoreElements()) {
         System.out.println("找不到包,请检查后重试");
         return;
     }
     loadClassFiles(resources.nextElement().getFile());
 }

 /**
  * 从指定资源路径扫描class文件
  * 控制是否扫描 参数路径下第一级类,不负责添加类文件到列表
  */
 public static void loadClassFiles(String pkgResourcePathName) {
     File pkg = new File(pkgResourcePathName);
     // 利用静态标记控制扫描参数路径包下第一级类文件
     for (File listFile : Objects.requireNonNull(pkg.listFiles(pathname -> scanMainPackageClass || !pathname.isFile()))) {
         loadClassFiles(listFile);
     }
 }

 /**
  * 递归扫描给定目录及目录下所有类文件,添加到静态列表
  */
 public static void loadClassFiles(File file) {
     if (file.isFile()) {
         if (file.getName().endsWith(".class")) {
             classFileList.add(file);
         }
         return;
     }
     for (File listFile : Objects.requireNonNull(file.listFiles())) {
         loadClassFiles(listFile);
     }
 }

声明:本文使用八爪鱼rpa工具从gitee自动搬运本人原创(或摘录,会备注出处)博客,如版式错乱请评论私信,如情况紧急或久未回复请致邮 xkm.0jiejie0@qq.com 并备注原委;引用本人笔记的链接正常情况下均可访问,如打不开请查看该链接末尾的笔记标题(右击链接文本,点击 复制链接地址,在文本编辑工具粘贴查看,也可在搜索框粘贴后直接编辑然后搜索),在本人博客手动搜索该标题即可;如遇任何问题,或有更佳方案,欢迎与我沟通!

相关推荐
Moshow郑锴3 分钟前
Java SpringBoot 疑难 Bug 排查思路解析:从“语法正确”到“行为相符”
java·spring boot·bug
CHANG_THE_WORLD6 分钟前
C++ 一维、二维、三维数组完整演示
开发语言·c++
APIshop15 分钟前
淘宝商品评论接口实战解析:从抓包到数据抓取全链路技术指南
java·python
~央千澈~17 分钟前
抖音弹幕游戏开发之第14集:添加更多整蛊效果·优雅草云桧·卓伊凡
开发语言·python·游戏
百锦再33 分钟前
线程安全的单例模式全方位解读:从原理到最佳实践
java·javascript·安全·spring·单例模式·kafka·tomcat
百锦再1 小时前
Java synchronized关键字详解:从入门到原理(两课时)
java·开发语言·struts·spring·kafka·tomcat·maven
油丶酸萝卜别吃1 小时前
什么是 Java 内存模型(JMM)?
java·开发语言
量子炒饭大师1 小时前
【C++入门】Cyber神经的义体插件 —— 【类与对象】内部类
java·开发语言·c++·内部类·嵌套类
Hx_Ma161 小时前
测试题(四)
java·开发语言·jvm
Never_Satisfied1 小时前
在c#中,抛出异常,并指定其message的值
java·javascript·c#