使用反射设置私有字段值
Set private field value with reflection
我有 2 个 classes:Father
和 Child
public class Father implements Serializable, JSONInterface {
private String a_field;
//setter and getter here
}
public class Child extends Father {
//empty class
}
考虑到我想在 Child
class:
中设置 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);
但我有一个例外:
Exception in thread "main" 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" });
根据 Class.getField
的 Javadoc(强调我的):
Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object.
此方法仅 returns public 字段。由于 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());
更改为 String str1 = (String) f1.get(cc);
,因为您需要提供字段的对象,而不是 class。
如果您想将您的字段保密,那么您需要检索 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
}
要访问私有字段,您需要将 Field::setAccessible
设置为 true。可以拉开场超class。此代码有效:
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);
这个也可以访问私有字段而无需执行任何操作
import org.apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);
使用来自 Apache Commons Lang 3 的 FieldUtils
:
FieldUtils.writeField(childInstance, "a_field", "Hello", true);
true
强制设置,即使该字段是private。
Kotlin 版本
使用以下扩展函数获取私有变量
fun <T : Any> T.getPrivateProperty(variableName: String): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
return@let field.get(this)
}
}
设置私有变量值获取变量
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)
}
}
获取变量使用:
val bool = <your_class_object>.getPrivateProperty("your_variable") as String
设置和获取变量使用:
val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
Java版本
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);
}
}
}
}
设置私有值使用
RefUtil.setFieldValue(<your_class_object>, "your_variableName", newValue);
获取私人价值使用
Object value = RefUtil.getPrivateFieldValue(<your_class_object>, "your_variableName");
我有 2 个 classes:Father
和 Child
public class Father implements Serializable, JSONInterface {
private String a_field;
//setter and getter here
}
public class Child extends Father {
//empty class
}
考虑到我想在 Child
class:
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);
但我有一个例外:
Exception in thread "main" 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" });
根据 Class.getField
的 Javadoc(强调我的):
Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object.
此方法仅 returns public 字段。由于 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());
更改为 String str1 = (String) f1.get(cc);
,因为您需要提供字段的对象,而不是 class。
如果您想将您的字段保密,那么您需要检索 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
}
要访问私有字段,您需要将 Field::setAccessible
设置为 true。可以拉开场超class。此代码有效:
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);
这个也可以访问私有字段而无需执行任何操作
import org.apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);
使用来自 Apache Commons Lang 3 的 FieldUtils
:
FieldUtils.writeField(childInstance, "a_field", "Hello", true);
true
强制设置,即使该字段是private。
Kotlin 版本
使用以下扩展函数获取私有变量
fun <T : Any> T.getPrivateProperty(variableName: String): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
return@let field.get(this)
}
}
设置私有变量值获取变量
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)
}
}
获取变量使用:
val bool = <your_class_object>.getPrivateProperty("your_variable") as String
设置和获取变量使用:
val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
Java版本
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);
}
}
}
}
设置私有值使用
RefUtil.setFieldValue(<your_class_object>, "your_variableName", newValue);
获取私人价值使用
Object value = RefUtil.getPrivateFieldValue(<your_class_object>, "your_variableName");