使用反射设置私有字段值

use*_*183 46 java reflection

我有2个班级:FatherChild

public class Father implements Serializable, JSONInterface {

    private String a_field;

    //setter and getter here

}

public class Child extends Father {
    //empty class
}
Run Code Online (Sandbox Code Playgroud)

有了反射,我想a_fieldChild课堂上设置:

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);
Run Code Online (Sandbox Code Playgroud)

但我有一个例外:

线程"main"中的异常java.lang.NoSuchFieldException:a_field

但如果我尝试:

Child child = new Child();
child.setA_field("123");
Run Code Online (Sandbox Code Playgroud)

有用.

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

method = cc.getClass().getMethod("setA_field");
method.invoke(cc, new Object[] { "aaaaaaaaaaaaaa" });
Run Code Online (Sandbox Code Playgroud)

Joh*_*ean 107

要访问私有字段,您需要设置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);
Run Code Online (Sandbox Code Playgroud)


Dav*_*der 43

使用Apache commons-lang3:

FieldUtils.writeField(childInstance, "a_field", "Hello", true);
Run Code Online (Sandbox Code Playgroud)

"真实"迫使它设置,即使是"私人".

  • 谢天谢地,我们从那些必须由 Spring Bean 依赖注入设置的愚蠢字段中逃脱出来。 (4认同)

Sac*_*San 5

这个也可以访问私有字段而无需做任何事情

import org.apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);
Run Code Online (Sandbox Code Playgroud)


akh*_*707 5

Kotlin 版本

使用以下扩展函数获取私有变量

fun <T : Any> T.getPrivateProperty(variableName: String): Any? {
    return javaClass.getDeclaredField(variableName).let { field ->
        field.isAccessible = true
        return@let field.get(this)
    }
}
Run Code Online (Sandbox Code Playgroud)

设置私有变量值获取变量

fun <T : Any> T.setAndReturnPrivateProperty(variableName: String, data: Any): Any? {
    return javaClass.getDeclaredField(variableName).let { field ->
        field.isAccessible = true
        field.set(this, data)
        return@let field.get(this)
    }
}
Run Code Online (Sandbox Code Playgroud)

获取变量使用:

val bool = <your_class_object>.getPrivateProperty("your_variable") as String
Run Code Online (Sandbox Code Playgroud)

设置和获取变量使用:

val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
Run Code Online (Sandbox Code Playgroud)

爪哇版

public class RefUtil {

    public static Field setFieldValue(Object object, String fieldName, Object valueTobeSet) throws NoSuchFieldException, IllegalAccessException {
        Field field = getField(object.getClass(), fieldName);
        field.setAccessible(true);
        field.set(object, valueTobeSet);
        return field;
    }

    public static Object getPrivateFieldValue(Object object, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Field field = getField(object.getClass(), fieldName);
        field.setAccessible(true);
        return field.get(object);
    }

    private static Field getField(Class mClass, String fieldName) throws NoSuchFieldException {
        try {
            return mClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            Class superClass = mClass.getSuperclass();
            if (superClass == null) {
                throw e;
            } else {
                return getField(superClass, fieldName);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

设置私有值使用

RefUtil.setFieldValue(<your_class_object>, "your_variableName", newValue);
Run Code Online (Sandbox Code Playgroud)

获取私有值使用

Object value = RefUtil.getPrivateFieldValue(<your_class_object>, "your_variableName");
Run Code Online (Sandbox Code Playgroud)