2016-01-28 4 views
1

Я набрал код, который генерирует два класса, которые я пишу их в буфер и компилирую их с помощью JavaCompiler. Мои классы похожи на мои .java-файлы;JavaCompiler дает ошибку при создании зависимого класса

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

(4-я строка является "... проходит ArrayList ..." и есть символ^в А)

Мой генератор код компилируется как это;

Сначала я заполнить буфер с моим шаблоном для классов типов затем скомпилировать, как это:

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 is;

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

Как я могу решить эту проблему?

+0

Как вы компилируете классы 'A' и' B'? Компилятор java должен знать о классе 'A', когда компилируется класс' B'. – SubOptimal

+0

Возможно, ваш код компиляции прав, и вы пропустите в 'B.java' только оператор' import java.util.ArrayList; '. – SubOptimal

+0

Вместо вызова 'JavaCompiler # run' (который фактически является' Tool # run'), возможно, вам придется создать специальную задачу компиляции с помощью [JavaCompiler # getTask] (https://docs.oracle.com/javase/8 /docs/api/javax/tools/JavaCompiler.html#getTask-java.io.Writer-javax.tools.JavaFileManager-javax.tools.DiagnosticListener-java.lang.Iterable-java.lang.Iterable-java.lang.Iterable -): он позволяет вам добавлять информацию, необходимую для компиляции, в частности, ** компиляционные единицы **. Также см. Http://stackoverflow.com/a/30038318/3182664 (но он также может работать с некоторыми ручными 'classpath' fiddling) – Marco13

ответ

1

Как указано в комментарии, компилятор должен знать о классе A при компиляции класса B. В приведенном ниже примере мы добавляем выходной каталог для скомпилированных классов /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")); 
Смежные вопросы