3

我有超过 250 个需要由它们组成的实例的子类,我不能坐在那里腼腆地粘贴new Class();250 次。无论如何使用反射来创建类的实例吗?创建实例时不需要构造函数。谢谢。

4

4 回答 4

3

我真的不理解你,但我试着猜测(未经测试):

public class Test {
    public static void main(String[] args) {
        Class[] classes = new Class[]{Class1.class, Class2.class, Class3.class};
        for (Class cls : classes) {
            Object myObject = cls.newInstance();
            -------^^^^^^^^-------
        }
    }
}

看看创建新的类实例

编辑:可能是 http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#forName(java.lang.String )

Class.forName("mypackage.MyClassname");
于 2012-09-21T22:14:14.597 回答
2

首先,您需要获取所有子类。这个特定的答案似乎是合法的,尽管我自己没有测试过。

然后遍历类并使用Class.newInstance(无参数构造函数)或Class.getConstructor当构造函数Constructor.newInstance有参数必须传递时创建实例。最终代码将如下所示:

Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeType>> subTypes = 
        reflections.getSubTypesOf(SomeType.class);
Set<SomeType> someTypes = new HashSet<SomeType>(subTypes.size());
for (Class<? extends SubType> subType : subTypes) {
    someTypes.add(subType.newInstance());
}
// Do something with someTypes here

这将获取子类,遍历它们,并为每个子类创建一个实例。这里有一些我没有做任何事情的例外。您可能还需要进行一些铸造(尽管我认为您不必这样做)。

编辑:我上面的回答显然会导致一些虚假的类加载。像这样创建您的子类集:

Reflections reflections = new Reflections(...); //see in other use cases
Set<String> subTypeFqns = reflections.getStore().getSubTypesOf(SomeClass.class.getName());
Set<Class<?>> subTypes = new HashSet<Class<?>>();
for (String fqn : subTypeFqns) {
    subTypes.add(Class.forName(fqn));
}

然后这些行:

for (Class<? extends SubType> subType : subTypes) {
    someTypes.add(subType.newInstance());
}

变成这样:

for (Class<?> subType : subTypes) {
    someTypes.add((SomeType) subType.newInstance());
}
于 2012-09-21T22:18:44.413 回答
0

您可以执行以下操作:

Class instantiableClass = Class.forName("package.subpackage.ClassName");
Object instance = instantableClass.newInstance();

仅当您的类只有默认构造函数或公共零参数构造函数时才有效。如果需要,可以循环、概括或复制代码。

对于更通用的解决方案,这可以帮助您理解为什么它是不可能的。你可以对任何你知道的课程做任何你想做的事,或者知道他们的名字,或者可以从任何来源访问他们的名字,或者以任何方式获得这样的最少信息。

但是如果没有任何关于这些类的知识,这是几乎不可能的。您必须在当前类路径中查找所有类,然后检查它们的继承树是否符合您的特定类。

于 2012-09-21T22:16:18.737 回答
0

这是一段代码,用于加载包的所有类,为其创建新实例并将它们放入哈希图中(我的所有类都继承自 Commande):

    this.actions = new HashMap<String, Commande>();

    ServletContext sc = this.getServletContext();

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    URL res = classLoader.getResource(COMMAND_DIRECTORY);
    File[] list = new File(res.getFile()).listFiles();
    String className = "";
    for (File f : list) {
        className = f.getName().replaceAll(".class$", "");
        try {
            Class<?> classe = Class.forName("org.commandes." + className);
            if (classe.getSuperclass() == Commande.class) {
                Commande c = (Commande) classe.newInstance();
                this.actions.put(c.getName(), c);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

在这里,COMMAND_DIRECTORY 对我来说是 org/commandes。

我不知道这是否是正确的方法,但这是我发现在 servlet 中实现命令设计模式(类似插件实现)的唯一方法。

于 2012-09-21T22:16:44.973 回答