2015-06-19 3 views
2

Я пытаюсь создать программу, основанную на операционной системе Pebble Smartwatch. У меня есть текстовый файл с именем PebbleOS_Faces.txt, который имеет все имена разных часов, которые у меня будут на часах.Как запустить файл .java с переменным именем

Я использую PrintWriter преобразовать содержимое в файл .java, а затем компилировать его, используя код, который я получил от this post. Он скомпилирован в папку build/classes/pebbleos (я использую Netbeans для Mac, если это имеет значение) рядом со всеми остальными классами. Я подтвердил, что все это работает правильно.

Что осталось для меня, чтобы запустить класс изнутри программы. Дело в том, что каждый класс имел бы другое имя, основанное на именах сторожевых часов в файле PebbleOS_Faces.txt. Как создать экземпляр класса с именем переменной?

+1

Кажется, что вы ищете [отражение] (https://docs.oracle.com/javase/tutorial/reflect/). – Seelenvirtuose

ответ

0

Я никогда не пробовал это с динамически генерируемых/скомпилированных классов, но ...

Попробуйте использовать Class.forName ("com.example.YourClassName"), чтобы получить ссылку на класс:

http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String)

, а затем использовать Class.newInstance() для создания экземпляра класса:

http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#newInstance()

Для этого, чтобы работать, com.example.YourClassName должен быть видимым для загрузчика классов.

Например:

Class clazz = Class.forName("com.example.YourClassName"); 
Object instance = clazz.newInstance(); 

newInstance() вызов будет работать только если ваш класс имеет конструктор без аргументов.

Если конструктор класса YourClassName требует аргументов, вы должны использовать несколько иной метод для вызова конкретного конструктора и передачи ему значений. Например, если у вас есть конструктор, как это:

YourClassName (Integer someInt, String SomeString)

Тогда вы могли бы сделать это, чтобы создать экземпляр YourClassName с помощью этого конструктора:

Class clazz = Class.forName("com.example.YourClassName"); 
Constructor constructor = clazz.getConstructor(Integer.class, String.class); 
Object instance = constructor.newInstance(anInteger, "aString"); 

Это, вероятно, поможет если каждый экземпляр YourClassName реализовал тот же interface или расширил тот же базовый класс, чтобы вы могли применить возвращаемое значение newInstance() к этому интерфейсу или базовому классу. Затем вы сможете вызвать методы интерфейса или базового класса в экземпляре. В противном случае ваш единственный способ вызвать полезные методы для объекта будет use reflection.

+0

Следуя вашим предложениям, я получаю следующую ошибку: Исключение в потоке «main» java.lang.ClassNotFoundException: PebbleOS_Default, где Default - это имя Watch Face. Возможно ли, что класс находится в неправильном каталоге? –

+0

Возможно. Каково имя пакета класса PebbleOS_Default? – Firefly

+0

Имя пакета - pebbleos, которое является тем же самым именем пакета, что и остальные файлы. –

0

Вы хотите использовать Отражение. Вы можете получить объект Class по имени, используя Class.forName(String). Вы можете вызвать конструктор с помощью Class.getConstructors()[0].newInstance(<insert constructor arguments here>) *. Убедитесь, что все классы наследуют общий суперкласс, так что вы можете сделать что-то вроде:

WatchFace face = Class.forName(watchFaceName).getConstructors()[0].newInstance(); 

* Это предполагает, что есть только один конструктор

Смежные вопросы