Search code examples
javareflectionclassloader

Dynamically Loading a pre-compiled class without reflection


In my specific case I'd like to load a class in runtime where: I have the class (and its definition) at compile time but I only find out the location of its containing jar at runtime. Somewhat reversed from the classic classloading case where the name of the class is only known at runtime.

Let's assume the class to load is org/animals/Cat.class and it is one class out of many in animals.jar. When I compile my program, animals.jar is in my compile time class path, because I know where it is, e.g: javac -cp <path to>/animals.jar Something.java

I can import it, reference it, and compile my program Something.java

import org.animals.Cat;

    ...
    Cat c = new Cat();
    c.makesound();

Now I deploy the program to a production system, where the location of animals.jar and other libraries is only known at runtime. If I knew the location, I could have used

java -cp <path to>/animals.jar Something

But I only find it out at runtime. I was hoping that I can use a URLClassLoader to make it work. Assuming the passed in runtime path to jar is stored under 'location', I can create a classloader that loads it:

URL url = new File(location + "/animals.jar").toURI().toURL();
URL[] urls = new URL[]{url};
URLClassLoader cLoader = new URLClassLoader(urls);

And then just use Cat in my program, as compiled, without having to resort to reflection. For example, this is what I'm trying to avoid:

Class clazz = cLoader.loadClass("org.animals.Cat")
Object o = clazz.newInstance();
Method m = o.getClass().getMethod("makesound", ...);

Is this indeed doable without reflection? can I cash on the benefit of knowing the class at compile time? or must I use reflection as in above.

Thank you.


Solution

  • If your Cat class is known to implement, say, some Animal interface then you can do Animal a = (Animal)o and start invoking Animal methods on a without any use of reflection.