设置公共成员时出现IllegalArgumentException

col*_*ebb 2 java reflection

我一直在玩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)

谢谢.

coo*_*ird 8

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字段的内容.

更新

正如toolkitChris所指出的,该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和声明所需字段的名称可能是更好的主意.