使用reflection设置私有字段值
我有两个class: Father
和Child
public class Father implements Serializable, JSONInterface { private String a_field; //setter and getter here } public class Child extends Father { //empty class }
有了reflection,我想在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);
但我有一个例外:
线程“main”中的exceptionjava.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" });
要访问私有字段,您需要将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);
使用Apache commons-lang3:
FieldUtils.writeField(childInstance, "a_field", "Hello", true);
“真实”迫使它设定,即使是“私人”。
这个也可以访问私有字段而无需做任何事情
import org.apache.commons.lang3.reflect.FieldUtils; Object value = FieldUtils.readField(entity, fieldName, true);
根据Class.getField
的Javadoc(强调我的):
返回一个Field对象,该对象反映此Class对象所表示的类或接口的指定公共成员字段 。
此方法仅返回公共字段。 由于a_field
是私有的,因此无法找到。
这是一个有效的代码:
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());
to String str1 = (String) f1.get(cc);
因为你需要给出字段的对象,而不是类。
如果要将字段保密,则需要检索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 }