Ответ 1
Эта строка, похоже, суммирует суть вашей проблемы:
Проблема заключается в том, что теперь вы не можете вызывать какие-либо новые методы (только переопределения) для класса реализации, так как ваша ссылочная переменная объекта имеет тип интерфейса.
Вы довольно застряли в своей текущей реализации, так как вам нужно не только выполнить бросок, но и вам нужно определить метод (ы), который вы хотите вызвать в этом подклассе. Я вижу два варианта:
1. Как указано в другом месте, вы не можете использовать строковое представление имени класса для приведения вашего отраженного экземпляра к известному типу. Тем не менее, вы можете использовать тест String
equals()
, чтобы определить, подходит ли ваш класс к типу, который вы хотите, а затем выполнить строковое кодирование:
try {
String className = "com.path.to.ImplementationType";// really passed in from config
Class c = Class.forName(className);
InterfaceType interfaceType = (InterfaceType)c.newInstance();
if (className.equals("com.path.to.ImplementationType") {
((ImplementationType)interfaceType).doSomethingOnlyICanDo();
}
} catch (Exception e) {
e.printStackTrace();
}
Это выглядит довольно уродливо, и это разрушает хороший управляемый конфигурацией процесс. Я не предлагаю вам это сделать, это просто пример.
2. Другой вариант, который у вас есть, - это расширить свое отражение от создания Class
/Object
, включив в него отражение Method
. Если вы можете создать Class
из строки, переданной из файла конфигурации, вы также можете передать имя метода из этого файла конфигурации и через отражение получить экземпляр самого Method
из вашего объекта Class
, Затем вы можете вызвать invoke
(http://java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object, java.lang.Object...)) на Method
, передав в экземпляр вашего класса, который вы создали. Я думаю, что это поможет вам получить то, что вам нужно.
Вот пример кода. Обратите внимание, что я взял на себя смелость жестко кодировать параметры для методов. Вы также можете указать их в конфиге, и им нужно будет отразить их имена классов, чтобы определить их Class
obejcts и экземпляры.
public class Foo {
public void printAMessage() {
System.out.println(toString()+":a message");
}
public void printAnotherMessage(String theString) {
System.out.println(toString()+":another message:" + theString);
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("Foo");
Method method1 = c.getDeclaredMethod("printAMessage", new Class[]{});
Method method2 = c.getDeclaredMethod("printAnotherMessage", new Class[]{String.class});
Object o = c.newInstance();
System.out.println("this is my instance:" + o.toString());
method1.invoke(o);
method2.invoke(o, "this is my message, from a config file, of course");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException nsme){
nsme.printStackTrace();
} catch (IllegalAccessException iae) {
iae.printStackTrace();
} catch (InstantiationException ie) {
ie.printStackTrace();
} catch (InvocationTargetException ite) {
ite.printStackTrace();
}
}
}
и мой вывод:
this is my instance:[email protected]
[email protected]:a message
[email protected]:another message:this is my message, from a config file, of course