Fun with Java Reflections: Access Private Member Fields/Methods of other Classes

June 12, 2010 | By Rakhitha | Filed in: Java Stuff.

This is a follow-up to my earlier post on Java Reflections.  In the earlier post I just showed how to invoke methods of an object dynamically using reflection. Here I am going to talk about accessing attributes of another object using reflection, with a little twist.

Just like my earlier post I’ll start this with an exercise.

Write a class with a private member variable only. No get/set methods. But add a toString() method to output the content of that private variable.

Like Following….

Now write another class. It should create an instance of above class, and set your name as the value of ‘name’ attribute in that object.

Like Following…

Obviously above code will not even compile. But the question is can we do that with reflections? Yes we can!

Here are the steps….

1. Create an instance of PrivateMembers class

PrivateMembers pm = new PrivateMembers();

2. Get the Field Object

We need to get hod of the reflection object that represent ‘name’ field before we can do anything on it.

In java reflections there is a class named Field for this. All we got to do is to get the Class object of PrivateMembers class and from that we can take the Field.

In Class class there is a getField(…) method just like getMethod(…) method. But that is not going to work in our case. Because if you read the documentation on above two methods, you will realize that they only work for public members. Instead we have to use getDeclaredField(…) function. This function works for fields with any access specifier as long as the field is defined /overridden in the class that the Class object directly refer to. In other words it does not work with inherited members. In case if you are wondering, there are getDeclaredMethod(…), getDeclaredConstructor(…) functions to deal with methods and constructors.

Ok enough talk, let’s get the Field object

Field nameField = pm.getClass().getDeclaredField("name");

3. Make the Field Accessible

This field is still is a private field. We need to first make it accessible to us. Here is how….

nameField.setAccessible(true);

What above call does is, it turn off any accessibility checks to our field. Now, when we going to set the value, it’s not going to complain about it.

4. Set the Value

Following is the code to set the value. We just use set(…) method of Field class. It takes two parameters. 1st one is the actual object that we are updating, which we can leave as null if the field is a static field. 2nd parameter is the value. In case if you are wondering there is a get() method to read the value from Field.

nameField.set(pm, "Raka");

Now you can print the content of the pm object and see the value inside it.

Following is how the code look like when everything is put together

Above approach is very useful when you want to write generic logic that read/update many objects of different classes, such as custom serialization logics, encoding logics or ORM logics.

Finally a few words on security. Accessing private members this way is not really a security threat. However you should be careful with what you do. Changing values of private members can mess inner workings of their class. Also in Java Security Manager you can prevent/control access to private members even if reflection is used. See Java Doc on setAccessible(…) method.

/Rakhitha


Tags: , , , , , , , , , , , ,