1

我有一个类名和类源代码列表。我需要在内存中编译这些类,以便在程序中使用它们。编译一个类很好,除非该类需要另一个必须编译的类。例如,如果我有 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);
}

第一个类返回真,第二个返回假。如果我设置了多个类,如 A 和 B,A 类工作,B 类失败。我该怎么办?

4

1 回答 1

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;
    }
}
于 2014-02-22T22:49:01.103 回答