Search code examples
javaparameter-passingprocessingclassloaderurlclassloader

Can I pass parameters to my dynamically created classes?


I am successfully loading a class from an external MyClass.class file at runtime, and am able to call it's methods assuming I know the name of them, which I do.

The problem I'm having is I cannot figure out how to pass a parameter to the constructor of the class I am loading.

How can I modify this to pass a parameter to MyClass's constructor? Also, how can I access MyClass's public variable: infoToAccess?

Here are the files I'm working with. (Keep in mind, ClassLoaderExample.pde was written for Processing, but other than sketchPath("") and the lack of a main function, it is identical.

ClassLoaderExample.pde: The main file that loads the class:

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import java.lang.ClassLoader;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

/////// FILE STRUCTURE /////
// ClassLoaderExample     //
// --this file            //
// --tmp                  //
// ----MyClass.class      //
////////////////////////////

// TODO
//   Send parameter to MyClass constructor (by reference)
//   Get public int number from MyClass

void setup()
{
    String className = "MyClass";
    Object instance;
    Method updateMethod;

    // sketchPath("") returns the directory this file is in
    File file = new File(sketchPath(""));
    try
    {
        URL url = file.toURL();
        URL[] urls = new URL[]{url};

        ClassLoader classLoader = new URLClassLoader(urls);
        Class<?> loadedClass = classLoader.loadClass("tmp."+className);

        try
        {
            instance = loadedClass.newInstance();
            updateMethod = loadedClass.getDeclaredMethod("update");

            // Calls MyClass's update() method
            try
            {
                updateMethod.invoke(instance);
            }
            catch (InvocationTargetException e) {System.out.println(e);}
            catch (IllegalAccessException    e) {System.out.println(e);}
        }
        catch (InstantiationException e) {System.out.println(e);}
        catch (IllegalAccessException e) {System.out.println(e);}
        catch (NoSuchMethodException  e) {System.out.println(e);}
    }
    catch (MalformedURLException  e) {System.out.println(e);}
    catch (ClassNotFoundException e) {System.out.println(e);}
}

MyClass.java: The class I am loading:

package tmp;
public class MyClass
{
    public int infoToAccess = 1337;

    public MyClass(int i)
    {
        System.out.println("MyClass constructor was called with numebr: " + i);
    }

    public void update()
    {
        System.out.println("Update was called.");
    }
}

Thanks for any help with this!


Solution

  • you can use the class you loaded to get hold of the constructor you need an use that to create a new instance.

    import java.lang.reflect.Constructor;
    
    ...
    
    Class<?> loadedClass = classLoader.loadClass("tmp."+className);
    try {
      Constructor<?> ctor=loadedClass.getConstructor(int.class);
      ctor.newInstance(42);
      ...
    }
    ...