編輯:我不清楚。我必須使用反射,因爲我正在從命令行解釋。我正在做相當於我提供的代碼示例的反思。將派生對象傳遞給想要使用java反射的超類的方法?
希望這不是重複的,因爲它似乎是每天要做的事情。
我有一個類A和一個擴展了A的類B.如果我在類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);
我做了什麼(使用反射)是:
- 得到它們的參數傳遞給函數的對象。
- 獲取參數的類
- 查找基於參數類的方法。
- 調用該方法,傳遞參數Objects。
如果我打算將一個A對象傳遞給C.doSomething(...),這很好用。但是,如果我想傳遞一個B對象爲C.doSomething(...)失敗的步驟3,與此錯誤:
java.lang.NoSuchMethodException: C.doSomething(B)
什麼是適當的方式來獲得C.doSomething認識到, B是A? (查找使用getDeclaredMethod(字符串名稱,類... parameterTypes)和通過B.class作爲參數類型的方法時)
編輯:
的情況下,有人想我會後我自己的解決方案看到一個很快被黑了的方式來做Roland Illig建議的事情。在這個例子中,我引用這些預先製作的變量:
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
}
希望這將幫助別人的某個時候!
這應該是工作。如果'B'是從'A'派生出來的,那麼它可以用在任何期望'A'對象的地方。這就是*多態*的全部內容。 –
事情是,沒有方法'doSomething(B)',只有'doSomething(A)'。代碼如何知道它應該調用該方法,因爲完全匹配的方法不可用? –
注:仔細閱讀問題 - 這是關於如何找到正確的方法與反思。 –