如何在运行时从外部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 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();
假设您要加载的类实现了特定的接口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