Wednesday, 12 July 2017

Reflection in Java

As per Wikipedia; in computer science, reflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at runtime.

Thus the Reflection API in Java provides the ability to examine or modify the runtime behavior of applications running in the Java virtual machine.

Using reflection API we can inspect a class and get information about the fields, methods, constructors, implemented interfaces, super classes at run time. We can invoke a method at run time. Using reflection we can also dynamically create and access Java arrays, examine the Enums. Using reflection we can even access a private field and invoke a private method from another class!

Where is it used?

Though you may not have a need to use reflection API in your application but you may be seeing its usage in many tools or applications you are using.

  1. The IDE like Eclipse giving you the list of methods in a class, auto completing the field or method name.
  2. Your persistence framework matching the fields in your objects with the fields in the DB table at runtime.
  3. Junit getting the information about the methods to be invoked.
  4. Spring framework getting the class information using the bean definition and also getting the setters and getters or constructor of the class. So you can say dependency injection in Spring depends heavily on reflection.

Drawbacks of Reflection

Reflection provides a lot of power so it should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. Some of the drawbacks of Reflection are –

  1. Performance Overhead – Since reflection resolves types dynamically certain JVM optimizations can’t be performed. Thus the reflective operations have slower performance than their non-reflective counterparts. That means use of reflection in the sections of code which are called frequently in performance-sensitive applications should be avoided.
  2. Security Restrictions - Reflection requires a runtime permission which may not be present when running under a security manager. Thus the code which has to run in a restricted security context should avoid reflection.
  3. Against Object oriented principles - Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.

Reflection API

Some of the main classes and interfaces which you will use while using reflection are as follows –

  • Class - For every type of object, JVM instantiates an immutable instance of java.lang.Class (Note that Class itself is not part of Reflection API) which provides methods to examine the runtime properties of the object including its members and type information. Class also provides the ability to create new classes and objects. Most importantly, it is the entry point for all of the Reflection APIs.
  • Member - Reflection defines an interface java.lang.reflect.Member which is implemented by java.lang.reflect.Field, java.lang.reflect.Method, and java.lang.reflect.Constructor which can be used to get information about class members.
  • Field - Field class provides methods for accessing type information and setting and getting values of a field on a given object.
  • Method - Method class provides methods for obtaining the type information for the parameters and return value. It may also be used to invoke methods on a given object.
  • Constructor - Constructor class provides methods for obtaining the information about the constructors of the class. If you reflectively invoke a constructor it will create a new instance of an object for a given class.
  • Array - The Array class provides static methods to dynamically create and access Java arrays. Reflection provides methods for accessing array types and array component types, creating new arrays, and retrieving and setting array component values.

Example code

Though we’ll go into more details about the Reflection API in posts about refelction API for class and refelction API for member but here also let’s see an example of Reflection API to get an idea about how to use it.

Here we have a class ClassA which has a constructor, private fields and getters and setters.

package org.prgm;

public class ClassA {
 private int i;
 private int j;
 // Constructor
 public ClassA(int i, int j){
  this.i = i;
  this.j = j;
 }
 public void setI(int i) {
  this.i = i;
 }
 public void setJ(int j) {
  this.j = j;
 }
 public int getI() {
  return i;
 }
 public int getJ() {
  return j;
 }
}

Using the following class you can get information about the constructor of the class, fields of the class and class methods.

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class ReflectionDemo {

 public static void main(String[] args) {
  try {
   Class<?> c = Class.forName("org.prgm.ClassA");
   // Getting constructors of the class
   Constructor<?>[] constructors = c.getConstructors();
   System.out.println("Constructors - " + Arrays.toString(constructors));
   
   // Getting all methods (even inherited) of the class
   Method[] methods = c.getMethods();
   System.out.println("All Methods - " + Arrays.toString(methods));
   
   // Getting methods of the class
   methods = c.getDeclaredMethods();
   System.out.println("Class Methods - " + Arrays.toString(methods));
   
   // Getting fields of the class
   Field[] fields = c.getDeclaredFields();
   System.out.println("Fields - " + Arrays.toString(fields));
   
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }  

 }

}

Output

Constructors - [public org.prgm.ClassA(int,int)]

All Methods - [public int org.prgm.ClassA.getI(), public void org.prgm.ClassA.setI(int), public void org.prgm.ClassA.setJ(int), 
public int org.prgm.ClassA.getJ(), public final void java.lang.Object.wait() throws java.lang.InterruptedException, 
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, 
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, 
public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), 
public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), 
public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]

Class Methods - [public int org.prgm.ClassA.getI(), public void org.prgm.ClassA.setI(int), public void org.prgm.ClassA.setJ(int), 
public int org.prgm.ClassA.getJ()]

Fields - [private int org.prgm.ClassA.i, private int org.prgm.ClassA.j]

Reference - https://docs.oracle.com/javase/tutorial/reflect/index.html

That's all for this topic Reflection in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Reflection in Java - Class
  2. Reflection in Java - Field
  3. Object cloning in java
  4. Serialization in Java

You may also like -

>>>Go to Java advance topics page

1 comment:

  1. you are posting a good information for people and keep maintain and give more update too.
    seo services in india

    ReplyDelete