简体   繁体   English

通过反射调用抽象方法

[英]Invoke an abstract method by reflection

I have a class SomeTaskManager with an abstract method runATask . 我有一个类SomeTaskManager和抽象方法runATask I want to execute the runATask method via reflection, this is my code : what am I missing? 我想通过反射执行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;
}  

I'm getting this errors 我遇到这个错误

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) 

Aha, here 啊哈

m.invoke(c, new Object[] { someParam, null, 1});

you're passing the Class instead of an instance of it. 您正在传递Class而不是其实例。 You need to pass pm (the concrete instance) to it instead: 您需要将pm (具体实例)传递给它:

m.invoke(pm, new Object[] { someParam, null, 1});

This problem would likely be spotted sooner by just reading the code if you used full and self-documenting variable names instead of nothing-saying abbreviations. 如果您使用完整的和自记录的变量名而不是不讲缩写的缩写,则只需阅读代码,很可能会早点发现此问题。 I'd suggest to work on that as well. 我建议也进行此工作。


Unrelated to the concrete problem, the following line 具体问题无关 ,下面一行

Class c = Class.forName( pm.getClass().getName() ); 

can be simplified as follows 可以简化如下

Class c = pm.getClass();

Use getMethods instead of getDeclaredMethods. 使用getMethods而不是getDeclaredMethods。 The getDeclaredMethods() method doesn't return those methods which are inherited but getMethods() returns both declared and inherited. getDeclaredMethods()方法不返回继承的那些方法,但是getMethods()返回已声明和继承的方法。

Presumably you can get Class<? extends SomeTaskManager> 大概可以得到Class<? extends SomeTaskManager> Class<? extends SomeTaskManager> for c with SomeTaskManager.class . SomeTaskManager.class Class<? extends SomeTaskManager> c Class<? extends SomeTaskManager> You shouldn't use c as an instance, it's a class. 您不应该将c用作实例,它是一个类。 You need to create a new instance of SomeTaskManager and use that. 您需要创建SomeTaskManager的新实例并使用它。

You can't create an instance of an abstract class with abstract methods. 您不能使用抽象方法创建抽象类的实例。 You must implement these methods in a subclass and instantiate that. 您必须在子类中实现这些方法并将其实例化。

Your question shows you aren't aware of how polymorphism works. 您的问题表明您不了解多态是如何工作的。 When you have a reference to a base class, wether its abstract or concrete, any method invoked on that reference will dynamically figure out the method to invoke at runtime based on the actual object. 当您拥有对基类的引用(无论其抽象还是具体的)时,在该引用上调用的任何方法都会动态地找出要在运行时基于实际对象调用的方法。 This process is called dynamic binding. 此过程称为动态绑定。 It's best if I show a simple example: 最好举个简单的例子:

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");
    }
}

So this code: 所以这段代码:

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
}

See how the type of shape variable doesn't determine which method is invoked? 看看shape变量的类型如何不能确定调用哪个方法? As we change the object shape points to we can change the method that is invoked. 当我们更改对象的形状点时,可以更改所调用的方法。 The type of shape only determines the interface you can use to invoke methods. 形状的类型仅决定可用于调用方法的接口。 But, it's the actual type of the reference it points to that determines which method is invoked. 但是,它是引用的实际类型,它确定了要调用的方法。

So this is a long answer to why you don't need to use reflection to invoke that method on an abstract class. 因此,这是为什么您不需要使用反射来在抽象类上调用该方法的长篇幅答案。 Just use polymorphism and it will call the right method "magically". 只需使用多态性,它将“神奇地”调用正确的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM