6

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

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

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

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

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

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

4

3 回答 3

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

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

于 2009-08-23T22:21:09.240 回答
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();
于 2009-08-23T22:12:49.927 回答
1

示例程序:

项目打印机:

public class Printer {

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

}

此项目导出为 Printer.jar。

打印机类具有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

于 2013-01-24T12:39:20.480 回答