Stack Exchange
Invoke an abstract method by reflection
I have a class SomeTaskManager with an abstract method runATask.
I want to execute the runATask method via reflection,
 this is my code : what am I missing?
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)


Erm, you can't execute an abstract method - there's nothing to execute.

You can if the method is implemented in a subclass, and an instance of that subclass is being used after being instantiated. Anyway, you need to show us the stack trace. We don't know what arguments the method needs, or the types of the arguments you're passing. Also, your loop should process the code on finding the "runATask" method then break, not skip over the ones that aren't that. That's a huge code smell.

@ChrisDennett - In that case, it's no longer an abstract method.

@user That pastebin doesn't contain any errors. But regardless, you should not post important information on external sites (your question would become worthless for Google(rs) when the information on external site disappears). Instead, you should edit your question and include it in there.

I still think that it is madness to invoke abstract methods. There is a reason they are abstract. You can't invoke what isn't there, aka abstract things.

sorry, first is my first post. the pastabin was wrong, now I puted the errors in the question

@FlorianH. the abstract method is in a non public API, this is the simplest way i found to call it


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. You need to pass pm (the concrete instance) to it instead:
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();


The problem is that the class SomeTaskManager (realy ApplicationPackageManager) can not be instanziated: using directly m.invoke(pm, new Object[] { someParam, null, 1}); i get  java.lang.IllegalArgumentException: object is not an instance of the class  ; and using m.invoke(c.newInstance() , new Object[] { someParam, null, 1}); i get  java.lang.InstantiationException: android.app.ContextImpl$ApplicationPackageManager

Passing pm should work. Did you change the class to something else or something? You seem to have posted incomplete code.

Use getMethods instead of getDeclaredMethods.  The getDeclaredMethods() method doesn't return those methods which are inherited but getMethods() returns both declared and inherited.

Presumably you can get Class<? extends SomeTaskManager> for c with SomeTaskManager.class. You shouldn't use c as an instance, it's a class. You need to create a new instance of SomeTaskManager and use that.
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?  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".
