Pages

Sunday, March 27, 2016

Reflection in Java

   Reflection is the ability of a computer program to examine and modify the structure and behavior of program at run time.

In layman's language it is a powerful and scary feature that should be used with caution. It is used to subvert the norm of information hiding in OOP. It has the ability to modify private members at runtime and thus the term class manipulator fits much better for Reflection.

Core abilities of Reflection:

1. Inspecting constructors, methods and their parameters
2. Inspecting class and method modifiers (private, public, final, abstract)
3. Getting/setting private data
4. Invoking public/private methods

1. Inspecting constructors, methods and their parameters

package com.reflection;
import java.lang.reflect.Method;

public class Test {
 public static void main(String[] args){
  Class c = "foo".getClass();
  System.out.println(c.getName());

  Method[] strMethods = c.getDeclaredMethods();
  for(Method m : strMethods){
   	System.out.println(m.getName());
   	Class parameterType[] = m.getParameterTypes();

   for(int i=0;i < parameterType.length;i++){
    System.out.println("\t" + parameterType[i].getName());
   }
  }
Output:

java.lang.String
equals
 java.lang.Object
toString
hashCode
compareTo
 java.lang.String
compareTo
 java.lang.Object
indexOf
 java.lang.String
 int
indexOf
 java.lang.String
indexOf
 int
 int
indexOf
 int
2. Inspecting class and method modifiers (private, public, final, abstract)

Lets define a class first named TestClass:

package com.reflection;

public class TestClass {
 private int foobar = 42;
 private String zap = "Not accessibe";
 
 public int foo(){
  return 1;
 }
 
 private String bar(String a){
  return a;
 }
}

Lets define a second class with main method:
package com.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test {
 public static void main(String[] args){
  TestClass t = new TestClass();
  Class c1 = t.getClass();
  Field[] fields = c1.getDeclaredFields();
  for(Field f : fields){
   System.out.println(f.getName() + " is a " +
      Modifier.toString(f.getModifiers()) + "  field");
  }
  Method[] methods = c1.getDeclaredMethods();
  for(Method m : methods){
   System.out.println(m.getName() + " is a " +
      Modifier.toString(m.getModifiers()) + "  field");
  }
 }  
}
Output:
foobar is a private  field
zap is a private  field
bar is a private  field
foo is a public  field

3.  Getting/setting private data


Using the same TestClass here, we can get the values of fields using the following code.

package com.singleton;

import java.lang.reflect.*;

public class Test {
	   public static void main(String[] args) {
	     try {          
	    	 TestClass t = new TestClass();
	    	 Class c1 = t.getClass();
	    	 Field[] fields = c1.getDeclaredFields();
	    	 for(Field f : fields){
	    		 f.setAccessible(true);
	    		 System.out.println("The value of field " + 
f.getName() + " is: " + f.get(t)); //Here, note that parameter
//for get is instance of a class i.e. t and not c1.      }         }     catch(Exception e) {        System.out.println(e.toString());     }   } }
Output:

The value of field foobar is: 42
The value of field zap is: Not accessible