如何加載未編譯的Java類?
您需要先編譯它。這可以用javax.tools
API以編程方式完成。這隻需要在本地機器上安裝JDK在JRE之上。
這裏的(留下明顯異常處理除外)基本開球例如:
// 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 "[email protected]".
其中產量喜歡
hello
world
[email protected]
進一步使用會比較容易,如果這些類implements
某個接口這已經是在類路徑中。
SomeInterface instance = (SomeInterface) cls.newInstance();
否則,你需要將Reflection API涉及訪問和調用(未知)方法/場。
也就是說和無關的實際問題:
properties.load(new FileInputStream(new File("ClassName.properties")));
讓java.io.File
依靠當前工作目錄是便攜麻煩配方。不要這樣做。將該文件放入classpath中,並使用ClassLoader#getResourceAsStream()
以及類路徑相對路徑。
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("ClassName.properties"));
只是一個脫離主題的問題。當我用你的方式加載屬性時,我得到一個空值,但當我做到這一點時,我得到的屬性Foo.class.getResourceAsStream()?你能幫我理解你的代碼嗎?謝謝。 – unj2 2010-06-01 15:44:15
該屬性文件顯然與'Foo'類放在同一個包中。如上所述,你需要指定一個類路徑相對路徑,例如'COM /示例/ filename.properties'。但是如果你可以保證屬性文件總是和'Foo'類在同一個包中,那麼'Class#getResourceAsStream()'也是可以的。您只會錯過將應用程序外部的屬性文件外部化的功能,以便可以在不修改/重新打包應用程序的情況下對其進行修改。 – BalusC 2010-06-01 16:18:06
'Files.write(source,sourceFile,StandardCharsets.UTF_8);'不爲我編譯。我想你想'Files.write(sourceFile.toPath(),source.getBytes());'。 – 2016-07-13 18:17:38