java-使用反射设置私有字段值

我有2个班级:a_fieldChild

public class Father implements Serializable, JSONInterface {

    private String a_field;

    //setter and getter here

}

public class Child extends Father {
    //empty class
}

通过反射,我想在Child类中设置a_field

Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();

Field f1 = cc.getClass().getField("a_field");
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc.getClass());
System.out.println("field: " + str1);

但我有一个例外:

线程“主”中的异常java.lang.NoSuchFieldException:a_field

但是,如果我尝试:

Child child = new Child();
child.setA_field("123");

有用。

使用setter方法,我有同样的问题:

method = cc.getClass().getMethod("setA_field");
method.invoke(cc, new Object[] { "aaaaaaaaaaaaaa" });
user1066183 asked 2020-07-30T03:16:59Z
5个解决方案
102 votes

要访问私有字段,您需要将Field::setAccessible设置为true。 您可以离开超类领域。 此代码有效:

Class<?> clazz = Child.class;
Object cc = clazz.newInstance();

Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
John McClean answered 2020-07-30T03:17:21Z
40 votes

使用Apache commons-lang3:

FieldUtils.writeField(childInstance, "a_field", "Hello", true);

即使设置为“私有”,“ true”也会强制设置它。

David Lavender answered 2020-07-30T03:17:45Z
4 votes

这个人也可以访问私有字段,而无需执行任何操作

import org.apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);
Sacky San answered 2020-07-30T03:18:05Z
0 votes

您可以使用Manifold的@Jailbreak进行直接的类型安全的Java反射:

@Jailbreak Child child = new Child();
child.a_field = "123;

jailbreak()在编译器中解锁子局部变量,以直接访问Child层次结构中的所有成员。

同样,您可以将jailbreak()扩展方法一次性使用:

child.jailbreak().a_field = "123";

通过jailbreak()方法,您可以访问Child的层次结构中的任何成员。

在这两种情况下,编译器都会像公共字段一样为您安全地解决字段访问,而Manifold会在后台为您生成有效的反射代码。

发现有关歧管的更多信息。

Scott answered 2020-07-30T03:18:47Z
-4 votes

根据Class.getField(强调我的)的Javadoc:

返回一个Field对象,该对象反映此Class对象表示的类或接口的指定公共成员字段。

此方法仅返回公共字段。 由于String str1 = (String) f1.get(cc.getClass());是私人的,因此找不到。

这是一个工作代码:

public class Main {

    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("Child");
        Object cc = clazz.newInstance();

        Field f1 = cc.getClass().getField("a_field");
        f1.set(cc, "reflecting on life");
        String str1 = (String) f1.get(cc);
        System.out.println("field: " + str1);
    }

}

class Father implements Serializable {
    public String a_field;
}

class Child extends Father {
//empty class
}

请注意,我还将行String str1 = (String) f1.get(cc.getClass());更改为2988717460985218018049,因为您需要提供字段的对象,而不是类。


如果要保持字段私有,则需要检索getter / setter方法并调用它们。 您提供的代码不起作用,因为要获取方法,还需要指定其参数,因此

cc.getClass().getMethod("setA_field");

一定是

cc.getClass().getMethod("setA_field", String.class);

这是一个工作代码:

public class Main {

    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("Child");
        Object cc = clazz.newInstance();
        cc.getClass().getMethod("setA_field", String.class).invoke(cc, "aaaaaaaaaaaaaa");
        String str1 = (String) cc.getClass().getMethod("getA_field").invoke(cc);
        System.out.println("field: " + str1);
    }

}

class Father implements Serializable {

    private String a_field;

    public String getA_field() {
        return a_field;
    }

    public void setA_field(String a_field) {
        this.a_field = a_field;
    }

}

class Child extends Father {
    //empty class
}
Tunaki answered 2020-07-30T03:19:38Z
translate from https://stackoverflow.com:/questions/32716952/set-private-field-value-with-reflection