动态实例化给定抽象父类的所有子类

4
有没有一种方法可以动态实例化抽象类的所有子类?
我目前所拥有的类似于这个:
public class CommandHandler {

    private Command info        = new Info();
    private Command prefix      = new Prefix();
    private Command roll        = new Roll();
    private Command coin        = new Coin();
    private Command invite      = new Invite();
    private Command quit        = new Quit();
    private Command restart     = new Restart();

}

抽象父类大致如下:

public abstract class Command {

    protected String name;
    protected String arguments;

    protected abstract void execute();

}

但是如果我想实例化所有扩展Command的类而不是一个个输入它们并在每次添加命令时都将它们添加到列表中,该怎么办?
如果我可以动态地实例化它们,那么我还能动态地操作它们吗?例如:一旦实例化了每个类,就将每个类添加到列表中。
或者有没有更好的设计方法可以以更简单的方式实现我想要的功能?
编辑:@Ash的解决方案在IDE中完美运行,但在使用jar时却无法正常工作。为使其在两种情况下均可运行,您只需更改的位置即可。
classPathList.addAll(ClasspathHelper.forClassLoader());

to

classPathList.addAll(ClasspathHelper.forJavaClassPath());

希望这有助于某些人!

2
如果我自己创建一个“Command”子类,你的“CommandHandler”怎么知道这个类呢?答案是:不行,编写代码时无法知道所有可能的子类。如果多种子类在编译时确实已知,请考虑使用“enum”。 - aioobe
这可能会有所帮助 https://dev59.com/qHRB5IYBdhLWcg3w1Kv0 - Shrinivas Shukla
@aioobe Java有反射处理这种问题的能力 - 在运行时可以确定哪些其他类可用。 - Elemental
2
你为什么需要这个? - MC Emperor
@MCEmperor 我想加载给定类的子类,而不必自己输入代码,因为我希望能够更轻松、更优雅地添加新的子类。命令是一个例子,但我认为还有很多其他应用程序可以使用这样的功能。 - user6818621
1个回答

3
如果您使用maven(如果没有,请使用:p),请添加以下依赖项:
<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>

如果您有一个没有参数的构造函数,那么您可以使用以下代码列出您想要的类:

public class Loader {

    public static void main(String[] args) {
        try {
            Set<URL> classPathList = new HashSet<URL>();
            classPathList.addAll(ClasspathHelper.forClassLoader());
            Set<Class<? extends Command>> result = new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner()).setUrls(classPathList)).getSubTypesOf(Command.class);

            List<Command> commands = new ArrayList<Command>();

            for (Class<? extends Command> c : result) {
                System.out.println(c.getSimpleName());
                commands.add(c.newInstance());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

那非常好!谢谢。我不知道这样的东西存在。另外,对于那些不想使用Maven的人来说,你需要以下的jar包才能让它工作:reflections-0.9.10.jar,javassist-3.19.0-GA.jar,guava-15.0.jar和annotations-2.0.1.jar。 - user6818621

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接