gpt4 book ai didi

java - 使用反射调用公共(public)方法

转载 作者:太空狗 更新时间:2023-10-29 16:33:34 26 4
gpt4 key购买 nike

我在编写 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(), "--------------------------");
}
}

这是我的 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: --------------------------

我查找了 NoSuchMethodFound 错误,大多数 stackoverflow 都说这是由于方法是 private 而我的方法是 public。 examine() 中的 invoke 方法应该返回 20,因为那是我在 MainActivity 中创建的对象的年龄。它只是抛出一个异常。帮助?

编辑 Alain O'Dea,感谢您的帮助。这是我必须更改才能使其正常工作的内容。

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

日志

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

结果你得到了这个堆栈跟踪:

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) 是一种非静态(实例)方法:

public int getAge() {
return Age;
}

触发该异常的问题源于这段代码:

Method m = method.getDeclaringClass().getMethod(method.getName(), Integer.TYPE);

这将要求一个不存在的方法 int methodName(例如 int getAge(int))触发 NoSuchMethodException。这是一个多余的步骤,因为您可以改为调用 方法 上的调用

但这不会单独工作,因为调用也有问题。因此,您必须使用对象而不是 null 进行反射调用。这也不是全部问题。该方法是 int getAge() 而不是 int getAge(int)。它不需要 int 参数。因此,您还需要从 invoke 中删除 0 参数。

这里是更正的行:

int temp = (int) method.invoke(obj); //first argument is the object to invoke on, ignored if static method

Object Method.invoke(Object,Object...)的文档有引用值(value):

public Object invoke(Object obj,
Object... args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException

Invokes the underlying method represented by this Method object, on the specified object with the specified parameters. Individual parameters are automatically unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary.

If the underlying method is static, then the specified obj argument is ignored. It may be null.

If the number of formal parameters required by the underlying method is 0, the supplied args array may be of length 0 or null.

If the underlying method is an instance method, it is invoked using dynamic method lookup as documented in The Java Language Specification, Second Edition, section 15.12.4.4; in particular, overriding based on the runtime type of the target object will occur.

If the underlying method is static, the class that declared the method is initialized if it has not already been initialized.

If the method completes normally, the value it returns is returned to the caller of invoke; if the value has a primitive type, it is first appropriately wrapped in an object. However, if the value has the type of an array of a primitive type, the elements of the array are not wrapped in objects; in other words, an array of primitive type is returned. If the underlying method return type is void, the invocation returns null.

Parameters:

  • obj - the object the underlying method is invoked from
  • args - the arguments used for the method call

Returns:

  • the result of dispatching the method represented by this object on obj with parameters args

Throws:

  • IllegalAccessException - if this Method object is enforcing Java language access control and the underlying method is inaccessible.
  • IllegalArgumentException - if the method is an instance method and the specified object argument is not an instance of the class or interface declaring the underlying method (or of a subclass or implementor thereof); if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion.
  • InvocationTargetException - if the underlying method throws an exception.
  • NullPointerException - if the specified object is null and the method is an instance method. ExceptionInInitializerError - if the initialization provoked by this method fails.

来源:http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)

关于java - 使用反射调用公共(public)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33850666/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com