6

これは、投稿された質問の続きです:実行時にjarファイルをロードする方法

メソッド呼び出しレベルに進む方法がわかりません。私の理解では、clazzオブジェクトから、getMethodまたはgetDeclaredMethodを使用して、invokeを呼び出すメソッドオブジェクトを取得しました。もちろん、invokeにはインスタンスが必要です。それでは、サンプルコードでdoRunと呼ばれるものでしょうか?

mainとは異なるメソッドを実行したいのですが(run呼び出しで呼び出されるdoRunオブジェクトでmainであると仮定して)、doRun.run()メソッド呼び出しを実行する必要がありますか?

元の投稿をさらに明確にするために、次のように質問します。doRun.run()は、clazz型のクラスオブジェクトのインスタンスを実行する新しいスレッドを開始しますか?

私のためにこれを片付けるのを手伝ってくれてありがとう。

「how-should-i-load-jars-dynamically-at-runtime」(申し訳ありませんが、ハイパーリンクは1つしか許可されていません)を確認しましたが、これは、参照した最初の投稿の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()行を調整して、好みのインターフェースを参照します。

次に、インスタンスメソッドを使用している場合は、contructor(例では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としてエクスポートされます。

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

于 2013-01-24T12:39:20.480 に答える