有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java java编译器在创建依赖类时出错

我编写了一个代码,生成了两个类,我将它们写入缓冲区,并用JavaCompiler编译它们。我的课是这样的。java文件

public class A{
    public A() { }
    public String toString(){ return "A";}
    }

public class B extends ArrayList<A> {
public B() {
    super();
}

public void addItem(A a) 
{
    this.add(a);
}

public void print() {
    this.print();
    }
}

像这样的

但是,类的名称是随机生成的,当我创建文件时,会出现如下错误:

symbol:   class A
location: class B  

./src/A.java:4: error: cannot find symbol

(第四行是“…扩展ArrayList…”a)下面有一个“^”符号

我的代码生成器编译如下

首先,我用类型类的模板填充缓冲区,然后按如下方式编译:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, f.getPath());

之后,我创建另一个缓冲区,并用我的B类型类模板填充它,然后像这样编译

System.out.println(f.getParentFile().getPath());
compiler.run(null, null, null, f.getPath());

f是

f = new File(("./src/" + name + ".java"));

我怎样才能解决这个问题


共 (2) 个答案

  1. # 1 楼答案

    如注释中所述,编译类B时,编译器需要了解类A。在下面的示例中,我们将编译类/tmp/bin/的输出目录添加到optionList中编译器的类路径中

    如果不需要在文件系统上创建源文件,则可以阻止在文件系统上创建源文件

    public class CompileDependent {
    
        public static void main(String[] args) {
            String sourceClassA = "public class A {"
                    + "  public String toString() {"
                    + "    return \"A\";"
                    + "  }"
                    + "}";
            String sourceClassB = "import java.util.ArrayList;"
                    + "class B extends ArrayList<A> {"
                    + "  public void addItem(A a) {"
                    + "    this.add(a);"
                    + "  }"
                    + "}";
    
            List<JavaFileObject> compilationUnits = new ArrayList<>();
            compilationUnits.add(new StringJavaFileObject("A.java", sourceClassA));
            compilationUnits.add(new StringJavaFileObject("B.java", sourceClassB));
    
            List<String> optionList = new ArrayList<>();
            // classpath from current JVM + binary output directory
            optionList.add("-classpath");
            optionList.add(System.getProperty("java.class.path") + ":/tmp/bin");
            // class output directory
            optionList.add("-d");
            optionList.add("/tmp/bin");
    
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(
                    null,
                    Locale.UK,
                    Charset.forName("UTF-8")
            );
    
            boolean compiled = compiler.getTask(
                    null,
                    fileManager,
                    null,
                    optionList,
                    null,
                    compilationUnits).call();
            System.out.println("compiled = " + compiled);
        }
    
        private static class StringJavaFileObject extends SimpleJavaFileObject {
    
            final String code;
    
            StringJavaFileObject(String name, String code) {
                super(URI.create("string:///" + name), Kind.SOURCE);
                this.code = code;
            }
    
            @Override
            public CharSequence getCharContent(boolean ignoreEncodingErrors) {
                return code;
            }
        }
    }
    

    或者在文件系统上创建Java源文件。类似于上面的代码,对compilationUnits做了一个小改动。假定文件已经存储在给定位置

    List<File> sourceFiles = new ArrayList<>();
    sourceFiles.add(new File("/tmp/A.java"));
    sourceFiles.add(new File("/tmp/B.java"));
    
  2. # 2 楼答案

    这应该是有帮助的

        public void CompileClasses(ArrayList<String> classesNames){
        //File helloWorldJava = new File("classes\\"+className+".java");
        try {
            List<String> optionList = new ArrayList<String>();
            optionList.add("-classpath");
            optionList.add(System.getProperty("java.class.path") + ";dist/InlineCompiler.jar");
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
            Iterable<? extends JavaFileObject> compilationUnit=null;
            ArrayList<File> files = new ArrayList<>();
            for (String className:classesNames) {
            files.add(new File(className+".java"));
            }
            compilationUnit = fileManager.getJavaFileObjectsFromFiles(files);
            JavaCompiler.CompilationTask task = compiler.getTask(
                    null,
                    fileManager,
                    diagnostics,
                    optionList,
                    null,
                    compilationUnit);
            if (task.call()) {
                URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()});
            } else {
                for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                    System.out.format("Error on line %d in %s%n %s",
                            diagnostic.getLineNumber(),
                            diagnostic.getSource().toUri(),
                            diagnostic.toString());
                }
            }
            fileManager.close();
        } catch (IOException exp) {
            exp.printStackTrace();
        }
    
    }