Вы можете использовать Отражения .
Reflections reflections = new Reflections("cz.milanhlinak.animal");
Set<Class<? extends Animal>> animals = reflections.getSubTypesOf(Animal.class);
См. Мой пример репозитория https://github.com/milanhlinak/62481200, где я использую Отражения + Google Guice для внедрения зависимостей.
Используя Reflections, вы можете получить все подтипы вашего класса Animal и добавить их в Google Guice Multibinder. После этого вы можете куда-то их ввести ...
// cz.milanhlinak.Module.java
public class Module extends AbstractModule {
@Override
protected void configure() {
Reflections reflections = new Reflections("cz.milanhlinak.animal");
Set<Class<? extends Animal>> animals = reflections.getSubTypesOf(Animal.class);
Multibinder<Animal> animalBinder = Multibinder.newSetBinder(binder(), Animal.class);
animals.forEach(animal -> animalBinder.addBinding().to(animal));
bind(AnimalProvider.class).to(AnimalProviderImpl.class).in(Singleton.class);
}
}
// cz.milanhlinak.animal.Animal.java
public abstract class Animal {
private final String sound;
public Animal(String sound) {
this.sound = sound;
}
void makeSound() {
System.out.println(this.sound);
}
}
// cz.milanhlinak.animal.Dog.java
public class Dog extends Animal {
public Dog() {
super("Bark");
}
}
// cz.milanhlinak.animal.Cat.java
public class Cat extends Animal {
public Cat() {
super("Meow");
}
}
// cz.milanhlinak.animal.AnimalProvider.java
public interface AnimalProvider {
Set<Animal> getAnimals();
}
// cz.milanhlinak.animal.AnimalProviderImpl.java
public class AnimalProviderImpl implements AnimalProvider {
private final Set<Animal> animals;
@Inject
public AnimalProviderImpl(Set<Animal> animals) {
this.animals = animals;
}
@Override
public Set<Animal> getAnimals() {
return this.animals;
}
}
Вы также можете проверить Google Guice - как автоматически добавлять привязку там, где я искал что-то подобное, но на основе кастомных аннотации.