Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/184.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用反射来调用公共方法_Java_Android_Reflection - Fatal编程技术网

Java 使用反射来调用公共方法

Java 使用反射来调用公共方法,java,android,reflection,Java,Android,Reflection,我正在编写一个API,在使用反射时遇到了一个问题。我要做的是从自定义对象类调用一个方法,并将值返回到调用的点。调用的开始发生在MainActivity.java中 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState)

我正在编写一个API,在使用反射时遇到了一个问题。我要做的是从自定义对象类调用一个方法,并将值返回到调用的点。调用的开始发生在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();
        }
    }
}
我的示例对象类旨在帮助确保此API正常工作

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;
    }
}
现在我遇到的主要问题是,当我在另一个名为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(), "--------------------------");
        }
    }
这是我的日志摘录:

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: --------------------------
我查找了NoSuchMethodFound错误,大多数stackoverflow说这是由于方法是
private
,但我的方法是
public
。examine()中的invoke方法应该返回20,因为这是我在MainActivity中创建的对象的年龄。但它只是抛出了一个异常。帮忙

编辑阿兰·奥黛,谢谢你的帮助。这是我必须改变的,以使其发挥作用

 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 {
                    int temp = (int) method.invoke(obj);
                    Log.d("" + this.getClass().getName(),"temp value: " + temp);
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

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

11-21 20:48:15.459 26949-26949/productions.widowmaker110.byteme D/Library.ByteMe: --------------------------
11-21 20:48:15.469 26949-26949/productions.widowmaker110.byteme D/Library.ByteMe: Method: getAge
11-21 20:48:15.469 26949-26949/productions.widowmaker110.byteme D/Library.ByteMe: Return Type: int
11-21 20:48:15.469 26949-26949/productions.widowmaker110.byteme D/Library.ByteMe: Class: class java.lang.reflect.Method
11-21 20:48:15.469 26949-26949/productions.widowmaker110.byteme D/Library.ByteMe: Declaring Class: class productions.widowmaker110.byteme.ExampleObject
11-21 20:48:15.469 26949-26949/productions.widowmaker110.byteme D/Library.ByteMe: temp value: 20
11-21 20:48:15.469 26949-26949/productions.widowmaker110.byteme D/Library.ByteMe: --------------------------
您有以下代码:

int temp = (int) m.invoke(null, 0); //first argument is the object to invoke on, ignored if static method
Method m = method.getDeclaringClass().getMethod(method.getName(), Integer.TYPE);
结果是,您得到了这个堆栈跟踪:

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: --------------------------
值得注意的是,getAge(int)是一种非静态(实例)方法:

触发该异常的问题源于以下代码:

int temp = (int) m.invoke(null, 0); //first argument is the object to invoke on, ignored if static method
Method m = method.getDeclaringClass().getMethod(method.getName(), Integer.TYPE);
这将要求使用一个不存在的方法intmethodname(例如intgetage(int)),触发NoSuchMethodException。这是一个多余的步骤,因为您可以只调用方法上的调用

但是,由于调用也有问题,所以这一点无法单独工作。因此,您必须对对象进行反射调用,而不是null。这也不是全部问题。方法是intgetage()而不是intgetage(int)。它不接受int参数。因此,您还需要从调用中删除0参数

以下是更正的行:

int temp = (int) method.invoke(obj); //first argument is the object to invoke on, ignored if static method
对象方法.invoke(对象,对象…)的文档可供参考:

在上调用此方法对象表示的基础方法 具有指定参数的指定对象。个人 参数将自动展开以匹配基元形式 参数,并且基本参数和参考参数都受 根据需要进行方法调用转换

如果基础方法是静态的,则指定的obj参数为 忽略。它可能是空的

如果基础方法所需的形式参数的数量 如果为0,则提供的args数组的长度可能为0或null

如果基础方法是实例方法,则使用 Java语言中记录的动态方法查找 规范,第二版,第15.12.4.4节;特别地, 将根据目标对象的运行时类型进行重写

如果基础方法是静态的,则声明该方法的类 如果尚未初始化,则初始化

如果方法正常完成,则返回它返回的值 调用方;如果该值具有基元类型,则为第一个 适当地包装在一个对象中。但是,如果值的类型为 对于基元类型的数组,数组的元素不是 包裹在物体中;换句话说,基本类型的数组是 返回。如果基础方法返回类型为void,则调用 返回null

参数:

  • obj—从中调用基础方法的对象
  • args-用于方法调用的参数
返回:

  • 调度由以下表达式表示的方法的结果 对象上具有参数args的对象
抛出:

  • IllegalAccessException-如果此方法对象正在强制 Java语言访问控制,底层方法是 难以接近
  • IllegalArgumentException-如果方法是 实例方法,指定的对象参数不是实例 声明基础方法的类或接口(或 子类或其实施者);如果实际和正式的 参数不同;如果为基元参数执行展开转换 失败;或者,如果在可能的展开之后,无法创建参数值 通过方法转换为相应的形式参数类型 调用转换
  • InvocationTargetException-如果 底层方法引发异常
  • NullPointerException-如果 指定的对象为null,该方法为实例方法。 ExceptionInInitializerError-如果此操作引发初始化 方法失败

来源:

如果您查看类的属性,您将看到
getMethod(字符串名称,类…参数类型)
接受表示方法名称(“getAge”在您的示例中)和参数类型(整数)的参数。您正在访问的类没有具有该签名的方法(
public int-getAge(int-age)
),因此出现NoSuchMethodException。这不是在骗你

另外,既然您已经有了要逐步执行的方法,为什么不直接调用
m.invoke(obj)
(如果它是正确的),而不是再次查询类中的方法呢?那可能会把事情弄清楚一点


最后,正如您的评论所说,当您调用
invoke()
时,您需要传递正在调用方法的对象,除非它是静态的(实际上不是)。因此,您需要将其更改为
m.invoke(obj)

@SotiriosDelimanolis从行
Method m=Method.getDeclaringClass().getMethod(Method.getName(),Integer.TYPE)中的对象类获取值;int temp=(int)m.invoke(null,0)//第一个参数是要调用的对象,如果静态方法Log.d(“+this.getClass().getName(),”temp value:“+temp”),则忽略该参数