samedi 21 novembre 2015

Use Reflection to invoke a public method

I'm writing an API and I ran into an issue with using reflection. What I want to do is call a method from a custom object class and return the value to the spot called. The start of the call occurs in the MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ByteMe b = new ByteMe();

        ExampleObject object = new ExampleObject("Bob", 20, "indy", "male", "its bobby");
        try {
            b.examine(object);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

My example object class is meant to help make sure this API works

public class ExampleObject {

    private String Name;
    private int Age;
    private String Location;
    private String Sex;
    private String Description;

    /**
     * Empty Constructor
     */
    public ExampleObject() {}

    /**
     * Basic constructor with initializing data
     *
     * @param _Name String with the name of the user
     * @param _Age Integer with the age of the user
     * @param _Location String containing the curret city and state of the user
     * @param _Sex String Male, Female, Transgender, or Other
     * @param _Description String short blurb about the user
     */
    public ExampleObject(String _Name, int _Age, String _Location, String _Sex, String _Description)
    {
        this.setName(_Name);
        this.setAge(_Age);
        this.setLocation(_Location);
        this.setSex(_Sex);
        this.setDescription(_Description);
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public int getAge() {
        return Age;
    }

    public void setAge(int age) {
        Age = age;
    }

    public String getLocation() {
        return Location;
    }

    public void setLocation(String location) {
        Location = location;
    }

    public String getSex() {
        return Sex;
    }

    public void setSex(String sex) {
        Sex = sex;
    }

    public String getDescription() {
        return Description;
    }

    public void setDescription(String description) {
        Description = description;
    }
}

Now the main issue I have is when I make this call within another file called ByteMe.java:

public void examine(Object obj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        //Get the list of possible methods held in this object.
        Method[] methods = obj.getClass().getMethods();

        // iterate through them
        for (Method method : methods) {
            Log.d("" + this.getClass().getName(), "--------------------------");
            Log.d("" + this.getClass().getName(), "Method: " + method.getName());
            Log.d("" + this.getClass().getName(), "Return Type: " + method.getReturnType());
            Log.d("" + this.getClass().getName(), "Class: " + method.getClass());
            Log.d("" + this.getClass().getName(), "Declaring Class: " + method.getDeclaringClass());

            if(method.getReturnType().getName().contains("int")) {
                try {
                    Method m = method.getDeclaringClass().getMethod(method.getName(), Integer.TYPE);
                    int temp = (int) m.invoke(null, 0); //first argument is the object to invoke on, ignored if static method
                    Log.d("" + this.getClass().getName(),"temp value: " + temp);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            Log.d("" + this.getClass().getName(), "--------------------------");
        }
    }

This is an excerpt of my logcat:

11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: --------------------------
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Method: equals
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Return Type: boolean
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Class: class java.lang.reflect.Method
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Declaring Class: class java.lang.Object
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: --------------------------
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: --------------------------
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Method: getAge
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Return Type: int
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Class: class java.lang.reflect.Method
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: Declaring Class: class productions.widowmaker110.byteme.ExampleObject
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err: java.lang.NoSuchMethodException: getAge [int]
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at java.lang.Class.getMethod(Class.java:664)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at java.lang.Class.getMethod(Class.java:643)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at Library.ByteMe.examine(ByteMe.java:94)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at productions.widowmaker110.byteme.MainActivity.onCreate(MainActivity.java:21)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.app.Activity.performCreate(Activity.java:5958)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2474)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.app.ActivityThread.access$800(ActivityThread.java:144)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1359)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.os.Looper.loop(Looper.java:155)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5696)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
11-21 20:08:11.704 18121-18121/productions.widowmaker110.byteme D/Library.ByteMe: --------------------------

I looked up the NoSuchMethodFound error and most of stackoverflow said it was due to the method being private but my method is public. The invoke method in examine() should return 20 since thats the age of the object I made in the MainActivity. It just throws an exception though. help?





Aucun commentaire:

Enregistrer un commentaire