Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get a list of all the implementations of an interface programmatically in Java?

Tags:

java

interface

Can I do it with reflection or something like that?

like image 878
user2427 Avatar asked Dec 07 '08 04:12

user2427


People also ask

Can an interface have multiple implementations Java?

Your class can implement more than one interface, so the implements keyword is followed by a comma-separated list of the interfaces implemented by the class. By convention, the implements clause follows the extends clause, if there is one.

Can we create list of interface?

Since List is an interface, objects cannot be created of the type list. We always need a class that implements this List in order to create an object. And also, after the introduction of Generics in Java 1.5, it is possible to restrict the type of object that can be stored in the List.

How does Java know interface implementation?

When you call a method on a variable declared as an interface, Java will look up which method to call in the instance's vtable, which is set when you create the instance based on the class. Thus, it actually calls the implementation definde by the class that that object is an instance of at runtime.


1 Answers

I have been searching for a while and there seems to be different approaches, here is a summary:

  1. reflections library is pretty popular if u don't mind adding the dependency. It would look like this:

    Reflections reflections = new Reflections("firstdeveloper.examples.reflections"); Set<Class<? extends Pet>> classes = reflections.getSubTypesOf(Pet.class); 
  2. ServiceLoader (as per erickson answer) and it would look like this:

    ServiceLoader<Pet> loader = ServiceLoader.load(Pet.class); for (Pet implClass : loader) {     System.out.println(implClass.getClass().getSimpleName()); // prints Dog, Cat } 

    Note that for this to work you need to define Petas a ServiceProviderInterface (SPI) and declare its implementations. you do that by creating a file in resources/META-INF/services with the name examples.reflections.Pet and declare all implementations of Pet in it

    examples.reflections.Dog examples.reflections.Cat 
  3. package-level annotation. here is an example:

    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());         }     } } 

    and the annotation definition:

    @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PACKAGE) public @interface MyPackageAnnotation {     Class<?>[] implementationsOfPet() default {}; } 

    and you must declare the package-level annotation in a file named package-info.java inside that package. here are sample contents:

    @MyPackageAnnotation(implementationsOfPet = {Dog.class, Cat.class}) package examples.reflections; 

    Note that only packages that are known to the ClassLoader at that time will be loaded by a call to Package.getPackages().

In addition, there are other approaches based on URLClassLoader that will always be limited to classes that have been already loaded, Unless you do a directory-based search.

like image 185
Ahmad Abdelghany Avatar answered Oct 12 '22 23:10

Ahmad Abdelghany