如何在 Java 中以编程方式获取接口的所有实现的列表?

新手上路,请多包涵

我可以用反射或类似的东西来做吗?

原文由 user2427 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 328
1 个回答

我已经搜索了一段时间,似乎有不同的方法,这里是一个总结:

  1. 如果您不介意添加依赖项, 反射 库非常受欢迎。它看起来像这样:
    Reflections reflections = new Reflections("firstdeveloper.examples.reflections");
   Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class);

  1. 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

  1. 包级注解。这是一个例子:
    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 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题