3

Is it possible to construct a List<Object> wherein the elements are uninstantiated classes, with the intention of getting one of the list elements and running a static method from that class or instantiating a new instance of that class? Also, how might one do this and how inadvisable is it (and why)?

To add some context: I want to make an application which generates a randomized city, placing buildings in the city, where each building is an instance of one of the many building classes, each inheriting from an abstract base class. To choose a building appropriate for a certain piece of land, the program may iterate over a list of all possible building classes, checking whether the required parameters can be met for that building (minimum / maximum height, footprint, shape, etc.) or these classes may be stored in some other manner, possibly using maps or some other structures. The bottom line is that I need to store (refferences?) to uninstantiated classes.

Void Star
  • 2,401
  • 4
  • 32
  • 57

2 Answers2

5

You cannot store types, but you can store the Class object for each class loaded by the JVM. When the JVM loads and initializes a class on the classpath, it creates a single Class object for that class.

The Class class gives you access to a number of instance methods for performing reflection on your program.

Also, how might one do this and how inadvisable is it (and why)?

For example

List<Class<?>> classes = new ArrayList<>();
classes.add(Example.class);

Now you can go through the elements and call different methods depending on what you want to do. If you want to create a new instance (and your class has a no-arg constructor), you can do

classes.get(0).newInstance();

If you don't have a no-argument constructor, you will need to get Constructor references from the Class object.

If you need to invoke methods (whether static or not), you need to get a Method reference. Read through the javadoc.

how inadvisable is it (and why)?

There are some things you cannot do without reflection, but it is generally discouraged.


You should try to minimize using Reflection when you can very well use the Factory pattern to achieve your goals in this situation.

User user2864740 suggests

I would have a list of "factories that know how to create the appropriate object", if practical - really depends upon where this data comes from and what role it has.

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • That answers my question quite nicely. user2864740 had a good suggestion (comment on my original question above) which I think may interest anyone with the same question as I do. I think it would be good to add that suggestion to the beginning of your answer since, as you say, reflection is "generally discouraged" (now I recall hearing an almost identical warning from my computer science professor who mentioned reflection very briefly). – Void Star Dec 22 '13 at 06:05
  • @BigEndian What that user suggested is the alternative (probably better in this case) of binding your classes at compile time. Reflection moves that binding to run time. – Sotirios Delimanolis Dec 22 '13 at 06:07
  • Yes, exactly. And doing things at compile time is arguably much cleaner and more robust, which is why I like the suggestion so much. – Void Star Dec 22 '13 at 06:09
  • I don't think it would hurt to add it to the answer. It is not strictly on topic but it is potentially quite a useful tip. That is your choice though. – Void Star Dec 22 '13 at 06:10
  • @bigEndian I would prefer they put a full answer, but I've linked their comment for now. – Sotirios Delimanolis Dec 22 '13 at 06:14
2

You can instantiate instances of a Class<?> like this -

List<Class<?>> al = new ArrayList<>();
al.add(java.util.Date.class);
for (Class<?> cls : al) {
  try {
    Constructor<?> ctor = cls.getConstructor(null);
    Object o = ctor.newInstance(null);
    System.out.println(o);
  } catch (Exception e) {
    e.printStackTrace();
  } 
}

Which, when I just ran it, output

Sun Dec 22 00:56:06 EST 2013
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • This was very helpful for me, my scenario included the complexity that the Classes over which I was iterating all extended an abstract class which I could cast `Object o` to, and then call the abstract methods. I'm still dubious of my patterns, but your answer helped close my loop. – yamori Jul 25 '16 at 21:16