我一直在玩Java中的反思......我有点困惑.
我希望下面的程序允许我更改类中公共成员变量的值.但是,我收到IllegalArgumentException.有任何想法吗?
public class ColinTest {
public String msg = "fail";
public ColinTest() { }
public static void main(String args[]) throws Exception {
ColinTest test = new ColinTest();
Class c = test.getClass();
Field[] decfields = c.getDeclaredFields();
decfields[0].set("msg", "success");
System.out.println(ColinTest.msg)
}
}
Run Code Online (Sandbox Code Playgroud)
我收到此消息 -
Exception in thread "main" java.lang.IllegalArgumentException
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:57)
at java.lang.reflect.Field.set(Field.java:656)
at ColinTest.main(ColinTest.java:44)
Run Code Online (Sandbox Code Playgroud)
谢谢.
该Field.set方法的第一个参数应该是您要反映的对象.
decfields[0].set("msg", "success");
Run Code Online (Sandbox Code Playgroud)
应该读:
decfields[0].set(test, "success");
Run Code Online (Sandbox Code Playgroud)
此外,最后的System.out.println调用应该引用test对象而不是类ColinTest,因为我认为其目的是输出test.msg字段的内容.
更新
正如toolkit和Chris所指出的,该Class.getDeclaredField方法可用于指定字段的名称以便检索它:
Field msgField = test.getClass().getDeclaredField("msg");
// or alternatively:
Field msgField = ColinTest.class.getDeclaredField("msg");
Run Code Online (Sandbox Code Playgroud)
然后,set所述的方法msgField可被调用:
msgField.set(test, "success");
Run Code Online (Sandbox Code Playgroud)
正如工具包已经指出的那样,这种方式有其好处,如果对象中添加了更多字段,则返回的字段的顺序Class.getDeclaredFields可能不一定将字段msg作为数组的第一个元素返回.根据返回的数组的顺序,某种方式可能会在对类进行更改时导致问题.
因此,使用getDeclaredField和声明所需字段的名称可能是更好的主意.
| 归档时间: |
|
| 查看次数: |
14388 次 |
| 最近记录: |