How to create instances of all subclasses

2019-05-15 13:28发布

I have over 250 subclasses that need instances made of them, and I can't sit there and coy and paste new Class(); 250 times. Is there anyway using Reflection to make an instnace of the classes? No constructor is needed when making the instance. Thanks.

4条回答
看我几分像从前
2楼-- · 2019-05-15 13:58

That's a chunk of code to load all the classes of a package, to create new instances for it and to put them in an hashmap (all my classes inherits from 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();
        }
    }

Here, COMMAND_DIRECTORY is org/commandes for me.

I don't know if this is the right way to do it, but it's the only way i found to implement the Command design pattern (plugin-like implemented) in a servlet.

查看更多
Emotional °昔
3楼-- · 2019-05-15 14:07

I really don't undesrtand you, but I try to guess (not tested):

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

Look at Creating New Class Instances

EDIT: May be http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#forName(java.lang.String)

Class.forName("mypackage.MyClassname");
查看更多
走好不送
4楼-- · 2019-05-15 14:15

You can do as follows:

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

Only works if your classes have only a default constructor, or public zero args constructor. The code may be looped, generalized or reproduced if you need.

For more general solution this may help you understand why it is not possible. You can do whatever you want with any classes you know, or know their name, or can access their name from any source, or be provided with such minimum information in any way.

But without any knowledge of that classes, it is hardly possible. You would have to seek for all classes in current classpath and then chceck their inheritance tree for compliance with your particular class.

查看更多
对你真心纯属浪费
5楼-- · 2019-05-15 14:18

First, you'll need to get all the subclasses. That particular answer seems legitimate, though I haven't tested it myself.

Then iterate through the classes and create the instances using either Class.newInstance (no-args constructors) or Class.getConstructor and Constructor.newInstance when there are parameters for the constructor that you have to pass. The final code will look something like this:

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

This will get the subclasses, iterate over them, and create an instance of each one. There are some exceptions here that I'm not doing anything with. You may also have to do some casting (though I don't think you have to).

Edit: My answer above will apparently cause some spurious class loading. Create your set of subclasses like this instead:

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

Then these lines:

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

Become this:

for (Class<?> subType : subTypes) {
    someTypes.add((SomeType) subType.newInstance());
}
查看更多
登录 后发表回答