РЕДАКТИРОВАТЬ: Я не понял. Мне нужно использовать отражение, потому что я интерпретирую из командной строки. Я делаю отражение, эквивалентное приведенным мною примерам кода.
надеюсь, что это не дубликат, потому что это кажется повседневным занятием.
У меня есть класс A и класс B, расширяющий A. Если у меня есть метод класса C, например public void doSomething (A a), как я могу использовать отражение для передачи объекта B в эту функцию? Я хочу сделать (отражение) эквивалент:
B b = new B(); //B inherits from A
C c = new C();
c.doSomething(b); // method signature is doSomething(A a);
Я сделал (используя отражение):
Это отлично работает, если я собираюсь передать объект A в C.doSomething (...). Однако, если я пытаюсь передать объект B в C.doSomething (...), на шаге 3 возникает ошибка:
java.lang.NoSuchMethodException: C.doSomething (B)
Что такое подходящий способ заставить C.doSomething распознать, что B - это A? (при поиске метода с использованием getDeclaredMethod (String name, Class ... parameterTypes) и передаче B.class в качестве типа параметра)
РЕДАКТИРОВАТЬ:
Я опубликую свое собственное решение на случай, если кто-то захочет увидеть один быстро взломанный способ сделать то, что предложил Роланд Иллиг. В этом примере я ссылаюсь на эти предварительно созданные переменные:
String methodToken; //the name of the method
Object obj; //the object whose method we are trying to call
Object[] args; //the user given arguments for the method
Class[] argTypes; //the types of the args gotten by args[i].getClass();
так что ...
//*** try to get the specified method from the object
Method m = null;
// if we are looking for a no-arg version of the method:
if(null == args)
{
try
{
m = obj.getClass().getMethod(methodToken, argTypes);
}
catch ( /*errors*/ )
{
// do stuff
}
}
else // if we are looking for a version of the method that takes arguments
{
// we have to do this type of lookup because our user arguments could be
// subclasses of the arguments required by the method. getMethod will not
// find a match in that case.
try
{
boolean matchFound = false;
Class c = obj.getClass();
do
{ // for each level in the inheritance hierarchy:
// get all the methods with the right name
//(matching the name that the user supplied for the method)
Method[] methodList = c.getMethods();
ArrayList<Method> matchingMethods = new ArrayList<Method>();
for( Method meth : methodList)
{
if(meth.getName().equals(methodToken))
{
matchingMethods.add(meth);
}
}
// check for a matching method signature
for( Method meth : matchingMethods)
{
// get the types of the arguments the method under
// investigation requires.
Class[] paramList = meth.getParameterTypes();
// make sure the signature has the required number of
// elements. If not, this is not the correct method.
if(paramList.length != args.length)
{
continue;
}
// Now check if each method argument is assignable from the
// type given by the user's provided arguments. This means
// that we are checking to see if each of the user's
// arguments is the same as, or is a superclass or
// superinterface of the type found in the method signature
//(i.e. it is legal to pass the user arguments to this
// method.) If one does not match, then this is not the
// correct method and we continue to the next one.
boolean signatureMatch = false;
for ( int i = 0; i < paramList.length; ++i)
{
if(paramList[i].isAssignableFrom( argTypes[i] ) )
{
signatureMatch = true;
}
else
{
continue;
}
}
// if we matched the signature on a matchingly named
// method, then we set the method m, and indicate
// that we have found a match so that we can stop
// marching up the inheritance hierarchy. (i.e. the
// containing loop will terminate.
if(true == signatureMatch)
{
m = meth;
matchFound = true;
break;
}
}
// move up one level in class hierarchy.
c = c.getSuperclass();
}
while(null != c && false == matchFound);
}
catch( /*errors*/)
{
// do stuff
}
}
// check that m got assigned
if(null == m)
{
System.out.println("From DO: unable to match method");
return false;
}
// try to invoke the method !!!!
try
{
m.invoke(obj, args);
}
catch ( /* errors */ )
{
// do stuff
}
Надеюсь, это когда-нибудь поможет кому-то!