Java 加载文件夹下的所有 class

在 Java 开发中,我们经常会遇到需要动态加载文件夹下的所有 class 的情况。动态加载 class 可以让我们在程序运行时根据需要动态地加载、创建对象和执行方法,极大地提升了程序的灵活性和扩展性。本文将介绍如何使用 Java 的反射机制和类加载器来加载文件夹下的所有 class。

反射机制

Java 的反射机制允许我们在运行时动态地获取类的信息,并调用类的方法、访问类的属性。通过反射机制,我们可以在不知道类名的情况下,根据类名字符串来获取对应的 Class 对象,进而实例化对象和调用方法。

获取 Class 对象

要动态加载文件夹下的所有 class,首先需要获取类的 Class 对象。Java 中有三种方式可以获取 Class 对象。

  1. 使用 Class.forName() 方法:
Class<?> clazz = Class.forName("com.example.MyClass");
  1. 使用 .class 语法:
Class<?> clazz = MyClass.class;
  1. 使用 ClassLoaderloadClass() 方法:
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class<?> clazz = classLoader.loadClass("com.example.MyClass");

实例化对象和调用方法

获取到 Class 对象后,我们就可以通过反射机制实例化对象和调用方法了。

  1. 实例化对象:
Object obj = clazz.newInstance();
  1. 调用方法:
Method method = clazz.getMethod("methodName", parameterTypes);
method.invoke(obj, args);

类加载器

类加载器(ClassLoader)是 Java 虚拟机(JVM)用来将字节码加载到内存并转换为 Class 对象的重要组件。Java 中有三种内置的类加载器:Bootstrap ClassLoader、Extension ClassLoader 和 App ClassLoader。

类加载器的层次结构

类加载器之间存在一个父子关系的层次结构。这个层次结构实现了双亲委派模型,即每个类加载器在加载类时会先委托给其父类加载器加载,只有在父类加载器无法找到对应的类时,才会由当前类加载器自己来加载。

下图是类加载器的层次结构示意图:

erDiagram
    classLoader <|-- bootstrapClassLoader
    classLoader <|-- extensionClassLoader
    classLoader <|-- appClassLoader
    classLoader <|-- customClassLoader

自定义类加载器

除了使用 Java 内置的类加载器,我们还可以自定义类加载器。自定义类加载器可以用来实现一些特殊的类加载需求,比如从网络、数据库或其他非传统的来源加载类。

自定义类加载器需要继承自 ClassLoader 类,并重写 findClass() 方法来实现类的加载逻辑。

public class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 自定义加载逻辑
    }
}

加载文件夹下的所有 class

现在我们已经了解了反射机制和类加载器的基本原理,下面我们将结合这两个概念,来实现加载文件夹下的所有 class。

public class ClassLoaderUtil {
    public static List<Class<?>> loadClassesFromFolder(File folder) throws ClassNotFoundException {
        List<Class<?>> classes = new ArrayList<>();
        if (folder.isDirectory()) {
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isFile() && file.getName().endsWith(".class")) {
                        String className = file.getName().substring(0, file.getName().lastIndexOf("."));
                        Class<?> clazz = Class.forName(className);
                        classes.add(clazz);
                    }
                }
            }
        }
        return classes;
    }
}

上述代码中,我们定义了一个 ClassLoaderUtil 类,其中的 loadClassesFromFolder() 方法用于加载文件夹下的所有 class。该方法接收一个 File 对象作为参数,遍历文件夹下的所有文件,找到以 .class 结尾的文件,通过反射机制获取对应的 Class 对象,并将其存入一个 List 中返回。

使用示例:

File folder = new File("path