How does one access a method from an external jar at runtime?

馋奶兔 提交于 2019-12-01 05:12:31
McDowell

Here is some reflection code that doesn't cast to an interface:

public class ReflectionDemo {

  public void print(String str, int value) {
    System.out.println(str);
    System.out.println(value);
  }

  public static int getNumber() { return 42; }

  public static void main(String[] args) throws Exception {
    Class<?> clazz = ReflectionDemo.class;
    // static call
    Method getNumber = clazz.getMethod("getNumber");
    int i = (Integer) getNumber.invoke(null /* static */);
    // instance call
    Constructor<?> ctor = clazz.getConstructor();
    Object instance = ctor.newInstance();
    Method print = clazz.getMethod("print", String.class, Integer.TYPE);
    print.invoke(instance, "Hello, World!", i);
  }
}

Writing the reflected classes to an interface known by the consumer code (as in the example) is generally better because it allows you to avoid reflection and take advantage of the Java type system. Reflection should only be used when you have no choice.

The code example

ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL },
    getClass().getClassLoader()
);
Class<?> clazz = Class.forName("mypackage.MyClass", true, loader);
Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class);
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
doRun.run();

assumes that the class you are loading implements a particular interface Runnable, and therefore it's reasonale to cast to that type using asSubclass() and invoke run().

What do you know about the classes you are loading? Can you assume that they implement a particualr interface? If so adjust the asSubClass() line to reference the interafce you prefer.

Then, yes if you are working with instance methods create an instance using the contructor, ctor in the example.

There is no starting of a thread in the example. Creating a new thread would just have needed a couple of lines more code

Thread myThread = new Thread(doRun);
myThread.start();

Sample Program:

Project Printer:

public class Printer {

    public void display(String printtext)
    {
        System.out.println(printtext);
    }

}

This project is exported as Printer.jar.

Printer Class has method display() which takes string as input.

Invoking code:

       URL url = new URL("file:Printer.jar"); 
       URLClassLoader loader = new URLClassLoader (new URL[] {url});
       Class<?> cl = Class.forName ("Printer", true, loader);
       String printString = "Print this";
       Method printit = cl.getMethod("display", String.class);
       Constructor<?> ctor = cl.getConstructor(); //One has to pass arguments if constructor takes input arguments.
       Object instance = ctor.newInstance();
       printit.invoke(instance, printString);
       loader.close ();

Output: Print this

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!