4

私は本当に奇妙な問題を抱えています。

URLClassLoader を使用して、ディレクトリからファイルを動的にインポートしています。リテラル文字列を使用するとコードは正常に動作し、変数をリテラル文字列に使用すると正常に動作しますが、これは必要なものではありません。

package test;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class Test {
    public static void main(String[] args) {

        try {
            File subfolder = new File("C:\\temp\\");
            URL classUrl = subfolder.toURI().toURL();
            URL[] classUrls = { classUrl };
            URLClassLoader ucl = new URLClassLoader(classUrls);

            for (File f : subfolder.listFiles()) {

                String name = f.getName()
                        .substring(0, f.getName().lastIndexOf(".")).trim();
                if (name.equals("TestClass"))
                        System.out.println(name);
                try {
                    MyInterface de = (MyInterface) Class.forName("TestClass", true, ucl)
                            .newInstance();
                    de.printSomething();
                } catch (ClassNotFoundException e) {
                }

                ucl.close();

            }
        } catch (MalformedURLException e) {
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

私が必要とするのは、これを行うことができることです:

MyInterface de = (MyInterface) Class.forName(name, true, ucl).newInstance();

しかし、「名前」は有効な文字列であり、「TestClass」と等しいにもかかわらず、機能しません。

編集: エラーが表示されます:

java.lang.ClassNotFoundException: TestClass
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at test.Test.main(Test.java:25)

どうしたの?

4

4 に答える 4

4

あなたの問題は、ロードされているクラスにパッケージがあるという事実に関係しているようです。Java は、これらのクラスをロードするときに、そのパッケージに関連するディレクトリ構造を見つけることを期待しています。したがって、次のコードが機能します。

try {
        File subfolder = new File("/home/glen/TestClass");
        URL classUrl = subfolder.toURI().toURL();
        URL[] classUrls = { classUrl };
        URLClassLoader ucl = new URLClassLoader(classUrls);

        for (File f : subfolder.listFiles()[0].listFiles()) {

            System.out.println(f.getName());

            String name = f.getName()
                    .substring(0, f.getName().lastIndexOf(".")).trim();// "TestClass";
            if (name.equals("TestClass"))
                    System.out.println(name);
            try {
                MyInterface de = (MyInterface) Class.forName("test." + name, true, ucl)
                        .newInstance();
                de.printSomething();
            } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }

            ucl.close();

        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

私がどのようであるかに注意してください:

  1. メソッドtest.TestClassで完全修飾クラス名 を指定するClass.forName
  2. 読み込みフォルダーの最初のサブディレクトリ (私の場合は "test" ディレクトリ) を列挙します。TestClass.class ファイルはそこにあります。そこから直接ロードしようとすると、パッケージ名を指定してもしなくても失敗します。

本質的に、URLClassLoader は のような JAR のようなディレクトリ構造を必要とし、ディレクトリ構造を含むtest/TestClass.classURL ルートを持ちます。

私の作業理論では、名前変数を文字列リテラルに変更するだけでなく、それを行っても問題なく動作するということです。他に何も変更していないことを再確認してください。いずれにせよ、これがあなたを正しい方向に導くことを願っています。

于 2015-08-27T13:43:19.210 に答える
3

どうしたの?

最初に間違っているのは、これが実際のコードではないということです。このコードは以下をキャッチして無視し ClassNotFoundExceptionます:

} catch (ClassNotFoundException e) {
}

したがって、表示されている出力を生成することはできません。

2 つ目の誤りは、これを修正すると、コードが期待どおりに機能することです。

再現できません。

実行していると思っていたコードを実行していないことは明らかです。Java は単に主張どおりに動作しません。

于 2015-08-27T05:05:39.583 に答える
2

それ以外の

MyInterface de = (MyInterface) Class.forName(name, true, ucl).newInstance();

使用する

MyInterface de = (MyInterface) Class.forName(name + "Class", true, ucl).newInstance();

私のために働きます。

于 2015-08-27T06:02:42.157 に答える