Instancing a class whose classname is a variable

I'm currently working on building a rudimentary 2D game engine and development kit program for building objects and I've run into an interesting problem. Here's what I want to do

1. User creates new object which extends one of my other types of objects with user-defined name

2. User defines constructor parameters and can alter the code of the object

3. User hits save button, program writes new file with <user-defined name>.java as it's name

4. Program compiles the objects

(This is where I am right now)

5. Program instances new object whose class is the newly created user defined class

6. Program saves newly instanced object (easy since they'll be serializable eventually)

7. Separate program opens the instanced object and uses it

Now then this poses 2 questions. 1, is there a better way to do this sort of thing? By this sort of thing I mean created a new java class, saving it, instancing it, and using it in a separate program. 2, the main question is, is this even possible? Is it possible to instance a class whose name is determined at runtime? Something tells me it's not possible, simply because that would make it really easy to write dynamic code that changes at runtime and since that's often talked about as a difficult thing I doubt there's any other why to do it. I have another possibility, but it would make loading these objects insanely difficult and since I want them to be editable that means I'd much rather use a different method. Also the other method has some other problems that are hard to explain without getting into what the program does.

I also would like to throw another question in.

What's the best (easiest to write) way to detect (at runtime) if one of your programs is performing an infinite recursion? I've been working on a very stupid recursion based pathfinding AI for the same program, it was originally loop based but I realized recursion would cut the code down by a lot and make it smarter. However recursion also introduced an infinite loop problem because the AI works by picking two paths when it hits an object, right and left, then examining those recursively. So when I hit an object, go right, and hit another object the AI tests going back the way it came and gets stuck. Any suggestions would be most appreciated, my current method is to pass each recursive call a list of the points already visited and check if the destination for that call is the same as any of those points then simply cancel going that way however that's not working too well.

Thanks for any help.

[2629 byte] By [Binksya] at [2007-11-27 8:29:36]
# 1

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#forName(java.lang.String)

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#newInstance()

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getConstructor(java.lang.Class...)

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Constructor.html#newInstance(java.lang.Object...)

ejpa at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 2

Wow, that looks to be exactly what I need. Thanks a lot.

However this has spawned a second question which has a much easier alternative (making all constructors take the same number of parameters) but which I'd like to ask anyway. It appears as though that newInstance() operator takes a number of Objects correct? If that is the case how would you determine at runtime how many Objects to put in?

Here's what I've got right now, I have a list of parameters in an Object[]. They're all either Integer or String due to the way my constructors work. Is there any possible way for me to call this newIsntance method with a variable number of parameters determined by the Object[]'s length besides just hard-coding it (if length == 1, else if length == 2 etc)? This is a pretty minor problem, and the problem that I thought might have been unsolvable has already been solved (ergo the Duke points are going there, even though a description of what the links were would have been nice) but I may as well ask it here.

Binksya at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 3

> Wow, that looks to be exactly what I need. Thanks a

> lot.

>

> However this has spawned a second question which has

> a much easier alternative (making all constructors

> take the same number of parameters) but which I'd

> like to ask anyway. It appears as though that

> newInstance() operator takes a number of Objects

> correct? If that is the case how would you determine

> at runtime how many Objects to put in?

You kind of need to know ahead of time, or have a way to get that input at runtim. You can call Class' getConstructors to list the constructors, but you'd stil have to figure out which one to call, either based on your program's logic and requirements or on some input from a user or other external source.

jverda at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 4

This notation:

public T newInstance(Object... initargs)

actually implies that the method can take an array as well. Demo:

import java.util.*;

public class DotDotDot {

static void f(String... args) {

System.out.println(Arrays.toString(args));

}

public static void main(String[] args) {

f("hello");

f("hello", "world");

String[] msg = {"hello", "world"};

f(msg);

}

}

Hippolytea at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 5

Wow...I was thinking I could get in and edit my old post before anyone responded...how wrong I was :P.

Jverd - I only have 2 constructors in each class, one that takes all necessary parameters, and the other that takes nothing. The problem is that these objects can extend one of 4 possible classes and each one takes a slightly different number of parameters.

Hippolyte - I'm not that familiar with the ... notation. Does that String... in the constructor imply that I need to do something like that with my actual constructors like change them from taking their current parameters to taking a single String... and going from there? I think I'm just making a simple mistake when it comes to how I'm thinking about this method but I don't know what mistake that is. Right now my constructors take a number of objects, like (String name, String description, int number) etc. Do I need to change that in order to properly utilize this method or can I do what I'm trying to do leaving that the same (I don't really have a problem with changing it, except I fear errors where too few parameters are passed to the constructor and I try to read the 12th object in an group of 11)

Binksya at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 6

> Jverd - I only have 2 constructors in each class, one

> that takes all necessary parameters, and the other

> that takes nothing. The problem is that these objects

> can extend one of 4 possible classes and each one

> takes a slightly different number of parameters.

Well, you have to either know at the time you write the code which c'tor you'll call, or you have to have a way to determine at runtime. So which of the following is it?

* You know now (or will know by the time you write the code) which c'tor you'll call for each class, and that won't change at runtime.

* You have rules by which you can determine at runtime which c'tor to call (even if you don't necessarily know yet how to realize those rules in Java).

* It is impossible to complete this.

jverda at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 7

> Hippolyte - I'm not that familiar with the ...

> notation. Does that String... in the constructor

> imply that I need to do something like that with my

> actual constructors like change them from taking

> their current parameters to taking a single String...

No. The final arg being Foo... is equivalent (or nearly so) to the final arg being Foo[]. It's called varargs. I never use it and don't recall the details of the rules, but you can read about it here:

http://java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html

jverda at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 8

We often don't know how many parameters a particular class will need to instantiate in any given situation. Or more accurately let me say that though they are the same type of thing their information needs may be wildly different from their cousin. Often what we do is put named values into a Map and pass the map into the factory. One of the keyed values is the fully qualified class. The factory grabs the map gets the class name and an instance of the class and passes the whole map into the constructor as a parameter. It then becomes the problem of the class to determine what values from the map it needs.

Yes we're passing extra values into the constructor as part of the map but it's a very small price to pay for having the flexibility we need.

PS.

puckstopper31a at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 9

Jverd - I know right now what constructor I'm calling and what arguments it takes...right now. That's subject to change and I would rather not dig through my code to find where I hard-coded it if another option is available.

Here's what I have right now, it's giving me an error that newInstance() cannot be applied to newInstance(Object[]). If I try to do newInstance(params[0], params[1]) etc based on the length of params it gives me the same error except it changes newInstance(Object[]) to newInstance(Object, Object) etc

Object[] params = new Object[textFields.size()];

for (int i=0; i<textFields.size(); i++)

{

if (parameters.get(i) == "int")

params[i] = Integer.parseInt(textFields.get(i).getText());

else if (parameters.get(i) == "String")

params[i] = textFields.get(i).getText();

else

params[i] = null;

}

obj = obj.newInstance(params);

I know I'm making a stupid mistake but I've never worked with that varargs thing before and so I don't know what stupid mistake I'm making. And in case it helps the constructor I'm trying to call at the moment is for my Item class which looks like this

public RoNItem(boolean isGrenade, boolean isMedpac, boolean isObjective, int weight, int numberOfItems, String pictureLocation, String name, String description, String soundClipLocation)

it takes 2 booleans (which I just noticed, so I guess my constructors take ints, Strings and booleans), 2 ints, and 4 strings right now. One of those strings was added yesterday, which is why I'd like to write some code that can adapt. The parameters the user is typing in are already loading from the file so the user will always enter the proper number and type of parameters, I just need to worry about how to pass those.>

Binksya at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 10

> Jverd - I know right now what constructor I'm calling

> and what arguments it takes...right now. That's

> subject to change and I would rather not dig through

> my code to find where I hard-coded it if another

> option is available.

The have a configuration file or user input or something that lists the classes of the args for the c'tor to call for each class.

> Here's what I have right now, it's giving me an error

> that newInstance() cannot be applied to

> newInstance(Object[]).

Class.newInstance doesn't take any args, but you're trying to pass an Object[]. That's what it's telling you.

You have to use Constructor.newInstance.

jverda at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...
# 11

Doh! Wow...I feel dumb, guess it was Constructor.newInstance rather than Class...

Well the code compiles now, that's an improvement :P. And it looks like, besides a few minor problems involving the placement of classes in subdirectories and then trying to access them without telling java where to look for them, this probably will work. Thanks for the all the help people.

Binksya at 2007-7-12 20:19:56 > top of Java-index,Java Essentials,Java Programming...