クラス名はプロパティファイルに保存されています。クラスストアがIDynamicLoadを実装することを知っています。クラスを動的にインスタンス化するにはどうすればよいですか?
今私は持っています
Properties foo = new Properties();
foo.load(new FileInputStream(new File("ClassName.properties")));
String class_name = foo.getProperty("class","DefaultClass");
//IDynamicLoad newClass = Class.forName(class_name).newInstance();
NewInstanceはコンパイルされた.classファイルのみをロードしますか? Javaコンパイルされていないクラスをロードするにはどうすればよいですか?
Javaコンパイルされていないクラスをロードするにはどうすればよいですか?
最初にコンパイルする必要があります。これは _javax.tools
_ API を使用してプログラムで実行できます。これには、JREの上のローカルマシンに [〜#〜] jdk [〜#〜] のみをインストールする必要があります。
基本的なキックオフの例は次のとおりです(明らかな例外処理は別として)。
_// Prepare source somehow.
String source = "package test; public class Test { static { System.out.println(\"hello\"); } public Test() { System.out.println(\"world\"); } }";
// Save source in .Java file.
File root = new File("/Java"); // On Windows running on C:\, this is C:\Java.
File sourceFile = new File(root, "test/Test.Java");
sourceFile.getParentFile().mkdirs();
Files.write(sourceFile.toPath(), source.getBytes(StandardCharsets.UTF_8));
// Compile source file.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());
// Load and instantiate compiled class.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName("test.Test", true, classLoader); // Should print "hello".
Object instance = cls.newInstance(); // Should print "world".
System.out.println(instance); // Should print "test.Test@hashcode".
_
のようになります
_hello
world
test.Test@ab853b
_
これらのクラスimplements
がすでにクラスパスにある特定のインターフェイスである場合、さらに使用するのはより簡単です。
_SomeInterface instance = (SomeInterface) cls.newInstance();
_
それ以外の場合は、(不明な)メソッド/フィールドにアクセスして呼び出すために Reflection API を含める必要があります。
とはいえ、実際の問題とは無関係です。
_properties.load(new FileInputStream(new File("ClassName.properties")));
_
_Java.io.File
_を現在の作業ディレクトリに依存させることは、移植性の問題のレシピです。しないでください。そのファイルをクラスパスに配置し、クラスパス相対パスで ClassLoader#getResourceAsStream()
を使用します。
_properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("ClassName.properties"));
_
BalusCの答えと同じように、私のキリムディストリビューションのこのコードには、もう少し自動化されたラッパーがあります。 https://github.com/kilim/kilim/blob/master/src/kilim/tools/Javac.Java
Javaソースを含む文字列のリストを取得し、パッケージとパブリッククラス/インターフェイス名を抽出し、tmpディレクトリに対応するディレクトリ/ファイル階層を作成します。その後、Javaコンパイラで、名前とクラスファイルのペア(ClassInfo構造体)のリストを返します。
コードを手伝ってください。 MITライセンス。
クラスに引数なしのパブリックコンストラクターがあることがわかっている場合、コメント付きのコードは正しいです。クラスが実際にIDynamicLoad
を実装することをコンパイラが認識できないため、結果をキャストする必要があります。そう:
IDynamicLoad newClass = (IDynamicLoad) Class.forName(class_name).newInstance();
もちろん、クラスをコンパイルし、クラスパス上で動作させる必要があります。
ソースコードからクラスを動的にコンパイルする場合、それはまったく別のやかんです。