我已经搜索了一段时间,似乎有不同的方法,这里是一个总结: 如果您不介意添加依赖项, 反射 库非常受欢迎。它看起来像这样: Reflections reflections = new Reflections("firstdeveloper.examples.reflections"); Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class); ServiceLoader (根据埃里克森的回答),它看起来像这样: ServiceLoader<Pet> loader = ServiceLoader.load(Pet.class); for (Pet implClass : loader) { System.out.println(implClass.getClass().getSimpleName()); // prints Dog, Cat } 请注意,要使其正常工作,您需要将 Pet 定义为 ServiceProviderInterface (SPI) 并声明其实现。您可以通过在 resources/META-INF/services 中创建一个名为 examples.reflections.Pet 的文件并在其中声明 Pet 的所有实现来实现 examples.reflections.Dog examples.reflections.Cat 包级注解。这是一个例子: Package[] packages = Package.getPackages(); for (Package p : packages) { MyPackageAnnotation annotation = p.getAnnotation(MyPackageAnnotation.class); if (annotation != null) { Class<?>[] implementations = annotation.implementationsOfPet(); for (Class<?> impl : implementations) { System.out.println(impl.getSimpleName()); } } } 和注释定义: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PACKAGE) public @interface MyPackageAnnotation { Class<?>[] implementationsOfPet() default {}; } 并且您必须在该包内名为 package-info.java 的文件中声明包级注释。以下是示例内容: @MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class}) package examples.reflections; 请注意,只有当时 ClassLoader 已知的包才会通过调用 Package.getPackages() 加载。 此外,还有其他基于 URLClassLoader 的方法将始终限于已经加载的类,除非您进行基于目录的搜索。 原文由 Ahmad Abdelghany 发布,翻译遵循 CC BY-SA 4.0 许可协议
我已经搜索了一段时间,似乎有不同的方法,这里是一个总结:
请注意,要使其正常工作,您需要将
Pet
定义为 ServiceProviderInterface (SPI) 并声明其实现。您可以通过在resources/META-INF/services
中创建一个名为examples.reflections.Pet
的文件并在其中声明Pet
的所有实现来实现和注释定义:
并且您必须在该包内名为
package-info.java
的文件中声明包级注释。以下是示例内容:请注意,只有当时 ClassLoader 已知的包才会通过调用
Package.getPackages()
加载。此外,还有其他基于 URLClassLoader 的方法将始终限于已经加载的类,除非您进行基于目录的搜索。