There are times when you wish you had some access to the information present in your Java classes. Information, such as which fields, methods and constructors are defined in it. This information is called as the metadata of a class and there is a way in which you can access easily without doing tedious coding or resorting to any hacks. It is called as Reflection.

Reflection in Java is done by using using the java.lang.Class class. This class provides access to all the information within your own applications classes or even the regular java library classes. Let’s say you have a class in a package called com.tt.company.Employee then if you need the metadata of the Employee class you would have to first assign it to the Class as :

Class c = Class.forName(“com.tt.company.Employee);

Accessing Fields, Methods and Constructors with Reflection

If you are not sure which fields and methods are declared in a class and you don’t have access to the source code then you can easily get this information by simple looping.

For example, if I wanted to access the fields and methods declared in the class Employee then its as simple as the below code.

Field[] fields = c.getFields();
 
Method[] methods = c.getMethods();
for (Field f : fields)
 
System.out.println("Field: " + f.getName());
 
for (Method m : methods)
 
System.out.println("Method:" + m.getName());

You might get some additional methods if you use the getMethods() method. This is because, the getMethods() definition also chooses those methods which are present in any of the super classes present. In this case, if Employee class does not have any super class, but still it is a subclass of Object. Hence methods defined in the Object class would also form a part of the output.

In order to avoid the methods defined in the super class you should use the getDeclaredMethods() instead.

Note: An important point worth mentioning over here is that, the loop would produce only those methods or fields which are marked public. If you don’t have a public field or method it won’t be considered. In order to loop over them, use the getDelcaredFields() or getDeclaredMethods()

Fun Things to do with Relection in Java

You can discover new techniques of programming once you feel the power of Reflection in your hands. The new techniques would include instantiation of objects dynamically, setting of values to fields and invoking methods without calling them explicitly.

Let’s take the case of a Singleton class into consideration for showing the true power of Reflection. For a Java novice, a singleton class is the one which has a private constructor. It isn’t practically true, but let’s assume that it is. Using reflection, this concept of singleton can be broken.

Here is an example of a Singleton class:

public class SingleCandidate {
 
private String name;
 
static int counter = 0;
private SingleCandidate() {
 
counter++;
 
System.out.println("Instance #" + counter);
 
}
public void showName() {
 
System.out.println(name);
 
}
 
}

A Singleton pattern dictates that only one instance of the object must be present at a given point of time in a JVM. So now, let’s take the above Singleton class for a ride with Reflection:

Class singleton = SingleCandidate.class;
 
Constructor privateConstructor =  singleton.getDeclaredConstructors()[0];
 
privateConstructor.setAccessible(true);
//This is scary
 
SingleCandidate obj = (SingleCandidate) privateConstructor.newInstance();
 
SingleCandidate obj2 = (SingleCandidate) privateConstructor.newInstance();

The code is self explanatory and you will realize that in this way you can easily create many instances of the possible candidate for a singleton class in the JVM. How fool proof was that?

Setting Values to Private Fields!

What did you learn in encapsulation? Was it making fields private and public so that private fields could be accessed only by the class in which they are declared?  Reflection can break this too.

//Even more scary
 
Field privateField = singleton.getDeclaredField("name");
 
privateField.setAccessible(true);
privateField.set(obj, "You are not a singleton anymore");
//Access private Constructor
 
System.out.println("Accessing private Constructor: " + privateConstructor.getName());//Get a private field value
 
System.out.println("Accessing private Field: " + privateField.get(obj));
//Invoke a method
 
Method method = singleton.getDeclaredMethod("showName");
 
method.invoke(obj);

Reflection with Generics

If you have tried out the above code in Eclipse you might see some warnings for the Class or Constructor usage. The warning message will be:

Class is a raw type. References to generic type Class<T> should be parameterized

Constructor is a raw type. References to generic type Constructor<T> should be parameterized

To suppress these warnings you will have to use the generic parameter “?” as follows:

Class<?> singleton = SingleCandidate.class;
 
Constructor<?> privateConstructor =  singleton.getDeclaredConstructors()[0];

The questions mark symbol is a wildcard type used in generics. This only applies only if you using Java 5 or higher versions.

Uses of reflection

Reflection is powerful technique when used appropriately. The major usage of reflection comes in when you are building your own framework, compilers or development tools in which you need access to the metadata of the classes created by end users. You surely might have already used the best products of Reflection without even knowing about it.

  • JSP gets converted to Servlets using Reflection.
  • The Spring framework uses Reflection to administer the references which you declare in your spring-config.xml without you explicitly instantiating any object. The whole concept of Dependency Injection (Inversion of Control) is conveniently implemented with Reflection.
  • Reflection also gave birth to the concept of aspect oriented programming.

Reflection is not limited just to this post and nor Reflection is used for the purpose of breaking security. This article was aimed at showing you a direction with which you can explore Reflection more and discover new principles and techniques to build better applications.


Stumble Digg Technorati Subscribe Delicious