[英]How To invoke a Method (with java reflection) from abstract class with generic type
[英]Invoke an abstract method by reflection
我有一个类SomeTaskManager
和抽象方法runATask
。 我想通过反射执行runATask
方法,这是我的代码:我缺少什么?
SomeTaskManager pm= (SomeTaskManager)context.getSomeTaskManager();
Class c = Class.forName( pm.getClass().getName() );
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
if (!m.getName().equals("runATask")) {
continue;
}
m.invoke( c ,new Object[] { someParam, null, 1});
break;
}
我遇到这个错误
java.lang.IllegalArgumentException: object is not an instance of the class
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at de.vogella.android.downloadmanager.DownloadManagerActivity.riflesso(DownloadManagerActivity.java:250)
at de.vogella.android.downloadmanager.DownloadManagerActivity.onCreate(DownloadManagerActivity.java:68)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
at android.app.ActivityThread.access$1500(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3835)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
java.lang.IllegalArgumentException: object is not an instance of the class at java.lang.reflect.Method.invoke(Method.java:507)
啊哈
m.invoke(c, new Object[] { someParam, null, 1});
您正在传递Class
而不是其实例。 您需要将pm
(具体实例)传递给它:
m.invoke(pm, new Object[] { someParam, null, 1});
如果您使用完整的和自记录的变量名而不是不讲缩写的缩写,则只需阅读代码,很可能会早点发现此问题。 我建议也进行此工作。
与具体问题无关 ,下面一行
Class c = Class.forName( pm.getClass().getName() );
可以简化如下
Class c = pm.getClass();
使用getMethods而不是getDeclaredMethods。 getDeclaredMethods()方法不返回继承的那些方法,但是getMethods()返回已声明和继承的方法。
大概可以得到Class<? extends SomeTaskManager>
用SomeTaskManager.class
Class<? extends SomeTaskManager>
c
Class<? extends SomeTaskManager>
。 您不应该将c
用作实例,它是一个类。 您需要创建SomeTaskManager
的新实例并使用它。
您不能使用抽象方法创建抽象类的实例。 您必须在子类中实现这些方法并将其实例化。
您的问题表明您不了解多态是如何工作的。 当您拥有对基类的引用(无论其抽象还是具体的)时,在该引用上调用的任何方法都会动态地找出要在运行时基于实际对象调用的方法。 此过程称为动态绑定。 最好举个简单的例子:
public class Shape {
public void draw() {
System.out.println("Draw a Shape");
}
}
public class Triangle extends Shape {
public void draw() {
System.out.println("Draw a Triangle");
}
}
public class Square extends Shape {
public void draw() {
System.out.println("Draw a Square");
}
}
所以这段代码:
public static void main( String[] args ) {
Shape shape = new Triangle();
shape.draw(); // prints Draw a Triangle
shape = new Square();
shape.draw(); // prints Draw a Square
shape = new Shape();
shape.draw(); // prints Draw a Shape
}
看看shape变量的类型如何不能确定调用哪个方法? 当我们更改对象的形状点时,可以更改所调用的方法。 形状的类型仅决定可用于调用方法的接口。 但是,它是引用的实际类型,它确定了要调用的方法。
因此,这是为什么您不需要使用反射来在抽象类上调用该方法的长篇幅答案。 只需使用多态性,它将“神奇地”调用正确的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.