2009-08-23 65 views
6

這是發佈的問題的延續:How to load a jar file at runtime在運行時如何從外部jar訪問方法?

我不確定如何繼續調用方法級別。根據我的理解,來自clazz對象的 ,我將使用getMethod或getDeclaredMethod來獲取我將調用調用的Method對象。當然,invoke需要一個實例。那麼在示例代碼中,這就是所謂的doRun?

即使我想執行與main不同的方法(假設它是使用運行調用調用的doRun對象的主要方法),是否需要執行doRun.run()方法調用?

只是爲了更詳細地解釋原文,請問: DoRun.run()是否會啓動一個執行類型爲clazz的類對象實例的新線程?

感謝您幫我解決這個問題。我看過「在運行時應該如何加載jar動態」(對不起,只允許一個超鏈接),但是這看起來在第一篇文章中違反了Class.newInstance的惡意箴言I引用。

回答

2

下面是一些反射代碼無法轉換爲一個接口:

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類型系統。只有當你別無選擇時纔會使用反射。

+0

因此,如果我理解了您的註釋,然後使用接口,我知道有什麼方法可用,並且可以在適當地投射實例對象之後直接編寫調用方法的代碼。這是真的? – Todd 2009-08-24 15:01:04

+0

當然,這假定原始代碼已經使用接口進行了編譯,而不是稍後創建的代碼並嘗試將實例轉換爲該實例。 – Todd 2009-08-24 15:35:11

+0

@Todd - 是的,你已經明白了。接口(或其他強類型實現)方法通常用於代碼已被寫入以動態實例化的插件。如果你正在對任意類進行自省和調用,這不是一個選項。 – McDowell 2009-08-24 15:47:06

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

假定正在加載的類實現一個特定的接口可運行的,因此它的reasonale投射到()的類型使用asSubclass並調用運行()。

你對加載的類有什麼瞭解?你能否假設他們實現了一個特殊的接口?如果是這樣,請調整asSubClass()行以引用您喜歡的交互。

然後,是的,如果你正在使用實例方法創建一個使用構造器的實例,在本例中爲ctor

示例中沒有線程的開始。創建一個新的線程將只是還需要幾行代碼更

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

DJNA - 感謝響應。不幸的是,我不能認爲我知道我可能會加載的課程。我有一個樣本案例可能不能指示真實世界的使用情況。就目前而言,我沒有繼承類,從構造函數中獲取實例,然後繼續使用getDeclaredMethod,類似於下面的帖子。感謝其他的澄清,我對運行調用感到困惑,認爲這意味着一個新的線程開始 - 我的不好。 – Todd 2009-08-24 14:59:50

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

相關問題