Set private field value with reflection

JavaReflection

Java Problem Overview


I have 2 classes: Father and Child

public class Father implements Serializable, JSONInterface {

	private String a_field;

    //setter and getter here

}

public class Child extends Father {
    //empty class
}

With reflection I want to set a_field in Child class:

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);

but I have an exception:

>Exception in thread "main" java.lang.NoSuchFieldException: a_field

But if I try:

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

it works.

Using setter method I have same problem:

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

Java Solutions


Solution 1 - Java

To access a private field you need to set Field::setAccessible to true. You can pull the field off the super class. This code works:

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);

Solution 2 - Java

Using FieldUtils from the Apache Commons Lang 3:

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

The true forces it to set, even if the field is private.

Solution 3 - Java

Kotlin verison

Get private variable using below extension functions

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

Set private variable value get the variable

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)
    }
}

Get variable use:

val bool = <your_class_object>.getPrivateProperty("your_variable") as String

Set and get variable use:

val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String

Java version

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);
            }
        }
    }
}

Set private value use

RefUtil.setFieldValue(<your_class_object>, "your_variableName", newValue);

Get private value use

Object value = RefUtil.getPrivateFieldValue(<your_class_object>, "your_variableName");

Solution 4 - Java

This one can access private fields as well without having to do anything

import org.apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);

Solution 5 - Java

As per the Javadoc of Class.getField (emphasis mine):

>Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object.

This method only returns public fields. Since a_field is private, it won't be found.

Here's a working code:

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
}

Note that I also changed your line String str1 = (String) f1.get(cc.getClass()); to String str1 = (String) f1.get(cc); because you need to give the object of the field, not the class.


If you want to keep your field private, then you need to retrieve the getter / setter method and invoke those instead. The code you have given does not work because, to get a method, you also need to specify it's arguments, so

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

must be

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

Here's a working code:

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
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1066183View Question on Stackoverflow
Solution 1 - JavaJohn McCleanView Answer on Stackoverflow
Solution 2 - JavaDavid LavenderView Answer on Stackoverflow
Solution 3 - Javaakhilesh0707View Answer on Stackoverflow
Solution 4 - JavaSacky SanView Answer on Stackoverflow
Solution 5 - JavaTunakiView Answer on Stackoverflow