如何在运行时从外部jar访问方法?

这是发布在以下问题的延续: 如何在运行时加载jar文件

我不确定如何继续方法调用级别。 根据我的理解,从clazz对象,我将使用getMethod或getDeclaredMethod来获取一个Method对象,我将从中调用invoke。 当然,调用需要一个实例。 那么那就是示例代码中所谓的doRun吗?

我是否需要执行doRun.run()方法调用,即使我想执行一个不同于main的方法(假设它是在运行调用调用的doRun对象上的主要方法)?

为了更好地澄清原始post,我问:doRun.run()是否启动了一个新线程来执行clazz类型的类对象的实例?

感谢您帮我解决这个问题。

我确实看过“how-should-i-load-jars-dynamic-at-runtime”(抱歉,只允许一个超链接),但这看起来违反了我引用的第一篇文章中的Class.newInstance邪恶警告。

这是一些不会转换为接口的reflection代码:

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); } } 

将reflection类写入消费者代码已知的接口( 如示例中 )通常更好,因为它允许您避免reflection并利用Java类型系统。 只有在你别无选择时才能使用reflection。

代码示例

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

假设您要加载的类实现了特定的接口Runnable,因此使用asSubclass()并调用run()来转换为该类型的原因。

您对正在加载的课程了解多少? 你能否假设他们实现了一个特殊的界面? 如果是这样,请调整asSubClass()行以引用您喜欢的交互。

然后,如果您正在使用实例方法,则使用构造函数创建实例,在示例中使用ctor

示例中没有启动线程。 创建一个新线程只需要几行代码

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

示例程序:

项目打印机:

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

该项目导出为Printer.jar。

Printer Class有方法display() ,它以字符串作为输入。

调用代码:

  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 (); 

输出: Print this