这是在How to load a jar file at runtime
中发布的问题的延续我不确定如何继续方法调用级别。根据我的理解, 从clazz对象,我将使用getMethod或getDeclaredMethod来获取一个Method对象,我将从该对象调用invoke。当然,调用需要一个实例。那么在示例代码中那会是什么叫做doRun?
我是否需要执行doRun.run()方法调用,即使我想执行一个不同于main的方法(假设它是使用运行调用调用的doRun对象的主要方法)?
为了进一步澄清原帖,我问: doRun.run()是否启动一个新线程来执行clazz类型的类对象的实例?
感谢您帮我解决此问题。
我确实看过“how-should-i-load-jars-dynamic-at-runtime”(抱歉,只允许一个超链接),但这看起来违反了我引用的第一篇文章中的Class.newInstance邪恶警告
答案 0 :(得分:3)
这是一些不会转换为接口的反射代码:
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);
}
}
将反射类写入消费者代码(as in the example)已知的接口通常更好,因为它允许您避免反射并利用Java类型系统。只有在你别无选择时才能使用反思。
答案 1 :(得分:2)
代码示例
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();
答案 2 :(得分:1)
示例程序:
项目打印机:
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