我有一个类名列表和类源代码。我需要在内存中编译这些类,以便我可以在程序中使用它们。编译一个类很好,除非该类需要另一个必须编译的类。例如,如果我有A类
package example;
public class A {
public A() {
doSomething();
}
}
该类工作正常,但是如果我必须在它之后编译这个类:
package example;
public class B {
private A holderForA;
public B() {
this.holderForA = new A();
}
}
B将无法成功编译。
这是我的编译代码(代码是前面提到的代码列表)和两个类。
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
for(String key : code.keySet()) {
CODE = code.get(key);
NAME = key;
JavaFileObject file = new JavaSourceFromString(NAME, CODE);
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
System.out.println("The task completed: " + task.call() + " for " + NAME);
}
第一个类返回true,第二个类返回false。如果我设置了多个类,如A和B,A类类可以工作,B类类失败。我该怎么办?
答案 0 :(得分:2)
我相信您的问题出在JavaSourceFromString类中,该类需要为类名编码URI:
@Test
public void test(){
Map<String, String> code = new HashMap<String, String>();
code.put("example.A",
"package example;\n" +
"public class A {\n" +
" public A() {\n" +
" doSomething();\n" +
" }\n" +
"}");
code.put("example.B",
"package example;\n" +
"public class B {\n" +
" private A holderForA;\n" +
" public B() {\n" +
" this.holderForA = new A();\n" +
" }\n" +
"}");
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
List<JavaFileObject> compilationUnits = new ArrayList<JavaFileObject>();
for(String key : code.keySet()) {
String toCompile = code.get(key);
JavaFileObject file = new Source(key, JavaFileObject.Kind.SOURCE, toCompile);
compilationUnits.add(file);
}
JavaCompiler.CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
System.out.println(task.call()+diagnostics.getDiagnostics().toString()); //passes every time
}
public class Source extends SimpleJavaFileObject {
private final String content;
public Source(String name, Kind kind, String content) {
super(URI.create("memo:///" + name.replace('.', '/') + kind.extension), kind);
this.content = content;
}
@Override
public CharSequence getCharContent(boolean ignore) {
return this.content;
}
}