2017-01-27 13 views
1

В настоящее время я делаю проект для своего университета. Я работаю над приложением, которое позволяет пользователю вводить java-методы в текстовую область. Затем приложение помещает эти методы в класс и должно скомпилировать его, когда пользователь нажимает кнопку компиляции.java: компилировать класс наследования во время выполнения

До сих пор я использовал этот подход: https://stackoverflow.com/a/2946402

И он работал на меня в первый, но он компилирует только простой (автономный) класс. Класс, который я должен скомпилировать во время выполнения, расширяет другой класс из приложения. Таким образом, пользователь должен получить доступ к некоторым методам из суперкласса, который я реализовал. Это метод я использую для компиляции класса:

public Class<?> loadClass(String filename) { 
     WorkingDirectory workingDirectory = WorkingDirectory.getInstance(); 
     File directory = workingDirectory.getCompileDirectory(); 
     File javaFile = workingDirectory.createJavaFileFromUserProgram(filename); 
     Class<?> cls = null; 
     try { 

      // Compile source file. 
      JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 

      compiler.run(null, null, null, javaFile.getPath()); 

      URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { directory.toURI().toURL() }); 
      cls = Class.forName(filename, true, classLoader); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return cls; 
    } 

Это прекрасно работает с классом, does'nt продлить ничего. Когда я добавляю расширяет я заканчиваю с этим сообщением об ошибке:

error: cannot find symbol 
    public class UsersClass extends ExistingClass { public void main() { 
            ^
     symbol: class ExistingClass 
    1 error 
    java.lang.ClassNotFoundException: UsersClass 
     at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
     at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
     at java.lang.Class.forName0(Native Method) 
     at java.lang.Class.forName(Class.java:348) 
     at utils.SimulatorClassloader.loadClass(SimulatorClassloader.java:51) 
     at simulator.Simulator.lambda$4(Simulator.java:171).... 

ли кто-то знает, что мне нужно добавить/изменить в моем методе? Я провел несколько исследований в течение нескольких часов, но с тех пор я не добился прогресса.

+0

вы создали 'ExisitingClass' тоже? – msagala25

+0

ExistingClass - это класс, который уже существует в этом приложении. Я его реализовал. Он содержит некоторые частные методы и некоторые общедоступные методы, которые пользователь может использовать, поскольку класс users расширяет существующий класс. UsersClass - это класс, который не существует в момент запуска приложения. Приложение создает файл .java и компилирует его, когда пользователь нажимает кнопку компиляции во время выполнения. – JWo

+1

Вы думаете, что 'UserClass' импортировал' ExistingClass', может быть, они находятся в другом пакете. Проверь это. – msagala25

ответ

0

Я не узнал некоторые ошибки, но с подсказкой LKTN.25 я их нашел.

Во-первых: у пользователейClass была опечатка в разделе импорта. После того, как эта ошибка исчезла, появилась еще одна ошибка.

Вторым: у моего базового класса не было конструктора по умолчанию и подкласса. И подкласс не переопределил другой конструктор. Поэтому не может быть создан экземпляр подкласса.

Видимо «Кто-нибудь знает, что мне нужно добавить/изменить в моем методе?» не был правильным вопросом. Ошибка была где-то в другом месте.

Обновление: Я думал, что мне нужно вставить конструктор в класс пользователей, потому что я не смог создать экземпляр во время выполнения. Класс пользователя вообще не нуждается в конструкторе (как обычно в java). Это получается из суперкласса.

Видимо, следующий фрагмент не работает.

Class<?> cls = new SimulatorClassloader().loadClass(this.simulatorGUI.getStageTitle()); 
       try { 
        Method method = cls.getMethod("main"); 
        try { 
         method.invoke(cls.newInstance()); 
        } catch (Exception e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } 

Но это (слегка измененный код) фактически делает работу:

Class<?> cls = new SimulatorClassloader().loadClass(this.simulatorGUI.getStageTitle()); 
       try { 
        Method method = cls.getMethod("main"); 
        try { 
         Object obj = cls.newInstance(); 
         method.invoke(obj); 
        } catch (Exception e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } 
+0

«Перезаписать»? Вы имеете в виду * override *? – EJP

+0

Да, я знаю. Простите за это. – JWo