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!