Accessing private members

The title of this post “Accessing private members from outside the class” may seem strange to some because the private modifier specifies that the member can only be accessed in its own class. It’s true that private members cannot be accessed from outside the class but there is an exception to this rule. Using Java Reflection you can inspect and modify Java classes (with some limitation) at runtime. Let us explore the concept of reflection with the help of some code:

class MyClass{
    private int a;
    public MyClass(){
        a=10;
    }
    private void show(){
        System.out.println("Value of a is "+a);
    }
}

The above code has two private data members int data member a and member function show().  The constructor would initialize the data member a to 10 when an instance of MyClass would be created.  However, any attempt to access the private data member a or the private member function show() would result in an error. For example:

class MyClass{
    private int a;
    public MyClass(){
        a=10;
    }
    private void show(){
        System.out.println("Value of a is "+a);
    }
}
class TestMyClass{
    public static void main( String args [] ){
        MyClass obj = new MyClass();
        obj.a=20;
    }
}

The above code would give the error “a has private access in MyClass” on line number 13. Similiarly, the following code would give an error “show() has private access in MyClass” on line number 13:

class MyClass{
    private int a;
    public MyClass(){
        a=10;
    }
    private void show(){
        System.out.println("Value of a is "+a);
    }
}
class TestMyClass{
    public static void main( String args [] ){
        MyClass obj = new MyClass();
        obj.show();
    }
}

The above two code examples proves that the private modifier specifies that the member can only be accessed in its own class as a and show() cannot be accessed from TestMyClass. In order to inspect or examine a class using reflection we must first obtain a class object. Since an instance of an object is available in this case, the simplest way to get its Class is to invoke Object.getClass():

Class cls = MyClass.class;

This reference cls can then be used to invoke getDeclaredField() function to returns a Field object that reflects the specified declared field of the class or interface represented by this Class object. This is done as follows:

Field f= cls.getDeclaredField("a");

Now we come to the important step of setting the accessible flag of object f to true. This is done by setAccessible() function as follows:

f.setAccessible(true);

A value of true indicates that the reflected object should suppress Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks. The last step is to access the value of the field by using the get() method as follows:

System.out.println(f.get(obj));

So the complete program to access the private data member from outside the class is as follows:

import java.lang.reflect.*;
class MyClass{
    private int a;
    public MyClass(){
        a=10;
    }
    private void show(){
        System.out.println("Value of a is "+a);
    }
}
class TestMyClass{
    public static void main( String args [] ) throws Exception{
        MyClass obj = new MyClass();
        Class cls = MyClass.class;
        Field f= cls.getDeclaredField("a");
        f.setAccessible(true);
        System.out.println(f.get(obj));
    }
}

The output of the above code would be 10 which is the value of the private data member assigned by the constructor. Accessing of private method is quite similar to accessing private data member. The function getDeclaredMethod() is used to retreive the required method and invoke() function is used to call the private data member. The code for invoking a private data member from outside the class is as follows:

import java.lang.reflect.*;
class MyClass{
    private int a;
    public MyClass(){
        a=10;
    }
    private void show(){
        System.out.println("Value of a is "+a);
    }
}
class TestMyClass{
    public static void main( String args [] ) throws Exception{
        MyClass obj = new MyClass();
        Class cls = MyClass.class;
        Method m= cls.getDeclaredMethod("show");
        m.setAccessible(true);
        m.invoke(obj);
    }
}

The output of the above code would be “Value of a is 10”, which the string which is being printed by the println() function at line number 8 contained in the private function show(). It’s possible to modify the value of the private data member by using the set() function. Following code would modify the value of a from 10 to 100 and then print the same to verify that the change has indeed been done:

import java.lang.reflect.*;
class MyClass{
    private int a;
    public MyClass(){
        a=10;
    }
    private void show(){
        System.out.println("Value of a is "+a);
    }
}
class TestMyClass{
    public static void main( String args [] ) throws Exception{
        MyClass obj = new MyClass();
        Class cls = MyClass.class;
        Field f=cls.getDeclaredField("a");
        f.setAccessible(true); 
        f.set(obj,100);
        System.out.println(f.get(obj));
    }
}

Thus we see that reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible. However, it is not suppose to be used indiscriminately  because of performance overhead, security restrictions and exposure of internals. The ground we covered in this article is not event the tip of the iceberg, interested students may consult Java documentation for details of the respective class. A very good resource on Java reflection is http://tutorials.jenkov.com/java-reflection/index.html

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.