Instantiating a Java Class loaded with a custom Classloader with a Constructor that needs arguments

Jul 04, 2003 16:49

Yes yes, quite a lengthy title I know.


Thing is, I have an IRC bot written in Java, and I have been using a custom ClassLoader to load modules for it. That way I can reload modules after recompiling them, without having to reload the whole bot.

My ClassLoader looks like this:

public class SimpleClassLoader extends URLClassLoader {

public SimpleClassLoader(URL[] paths) {
super(paths);
}

public Class load(String name) throws ClassNotFoundException {
return findClass(name);
}
}

Quite simple eh? Never understood why URLClassLoader is abstract, but oh well.

Now how to use it:

SimpleClassLoader loader = new SimpleClassLoader(paths);
IRCEventHandler handler = (IRCEventHandler) (loader.load(name).newInstance());

Now something I learned today. Don't use one loader to load the same class multiple times. Either cache the Class object and call newInstance() on it multiple times, or instantiate a new loader (of course, the last one is quite bad programming, some cases excepted). Actually my SimpleClassLoader should be extended with that. I'll do that when I have the urge =)

Now this is all fine and dandy if you want to instantiate a class that has an empty argument list for the Constructor. For instance:

Object bla = new Object();

But what if you want to make an instance of an object that does not have that possibility? Say:

Equation eq = new Equation("2 + 4");

You could rewrite Equation to have an empty argument list Constructor, but if you don't have the source that's out of the question. And writing a wrapper class is no good, because then the Class you are trying to instantiate will not be loaded through your ClassLoader.

So I got frustrated and searched the web. Couldn't find anything. So I start looking at the Java API docs again.

What did I find? The class Class has a method getConstrutor(Class[]) (as well as getContructors()). Meaning you give it an array containing Class objects that describe a list of arguments, and it will return a Constructor instance, which has a method newInstance(Object[]). That method is passed an array containing all arguments for the contructor.

So. A quick example:

String string = new String();
Class[] classes = { string.getClass() };
try {
eqConstructor = loader.load("net.drwilco.utils.Equation").getConstructor(classes);
} catch (Exception e) {
System.err.println("can't make Equation constructor");
}

And making an instance with that would look like:

Object[] args = { "2 + 4" };
Equation equation;
try {
equation = (Equation) eqConstructor.newInstance(args);
} catch (Exception e) {
logErrorOrQuitOrWhatever();
}

Et voila!
Previous post Next post
Up