Monday 22 June 2015

Reflections in java



Reflections,

  • The reflection API
  • How to use reflections
  • Advantages of reflections
  • Drawbacks of reflections

Java Reflection is a process of examining or modifying the run time behavior of a class at run time.

The java.lang.Class class provides many methods that can be used to get metadata, examine and change the run time behavior of a class.

The java.lang and java.lang.reflect packages provide classes for java reflection.

Where it is used,(Advantages)
The Reflection API is mainly used in:
  • IDE (Integrated Development Environment) e.g. Eclipse, MyEclipse, NetBeans etc.
  • Debugger
  • Test Tools etc.
The java.lang.Class class performs mainly two tasks:
  • provides methods to get the metadata of a class at run time.
  • provides methods to examine and change the run time behavior of a class.

Commonly used methods of Class class:

Method
Description
1) public String getName()
returns the class name
2) public static Class forName(String className)throws ClassNotFoundException
loads the class and returns the reference of Class class.
3) public Object newInstance()throws InstantiationException,IllegalAccessException
creates new instance.
4) public boolean isInterface()
checks if it is interface.
5) public boolean isArray()
checks if it is array.
6) public boolean isPrimitive()
checks if it is primitive.
7) public Class getSuperclass()
returns the superclass class reference.
8) public Field[] getDeclaredFields()throws SecurityException
returns the total number of fields of this class.
9) public Method[] getDeclaredMethods()throws SecurityException
returns the total number of methods of this class.
10) public Constructor[] getDeclaredConstructors()throws SecurityException
returns the total number of constructors of this class.
11) public Method getDeclaredMethod(String name,Class[] parameterTypes)throws NoSuchMethodException,SecurityException
returns the method class instance.

How to get the object of Class class?

There are 3 ways to get the instance of Class class. They are as follows:
  • forName() method of Class class
  • getClass() method of Object class
  • the .class syntax

1) forName() method of Class class

  • is used to load the class dynamically.
  • returns the instance of Class class.
  • It should be used if you know the fully qualified name of class.This cannot be used for primitive types.
Let's see the simple example of forName() method.
  1. class Simple{}  
  2.   
  3. class Test{  
  4.  public static void main(String args[]){  
  5.   Class c=Class.forName("Simple");  
  6.   System.out.println(c.getName());  
  7.  }  
  8. }  
Output:Simple

2) getClass() method of Object class

It returns the instance of Class class. It should be used if you know the type. Moreover, it can be used with primitives.
  1. class Simple{}  
  2.   
  3. class Test{  
  4.   void printName(Object obj){  
  5.   Class c=obj.getClass();    
  6.   System.out.println(c.getName());  
  7.   }  
  8.   public static void main(String args[]){  
  9.    Simple s=new Simple();  
  10.    
  11.    Test t=new Test();  
  12.    t.printName(s);  
  13.  }  
  14. }  
  15.    
Output:Simple

3) The .class syntax

If a type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type.It can be used for primitive data type also.
  1. class Test{  
  2.   public static void main(String args[]){  
  3.    Class c = boolean.class;   
  4.    System.out.println(c.getName());  
  5.   
  6.    Class c2 = Test.class;   
  7.    System.out.println(c2.getName());  
  8.  }  
  9. }  
Output:boolean
       Test

Determining the class object

Following methods of Class class is used to determine the class object:
1) public boolean isInterface(): determines if the specified Class object represents an interface type.
2) public boolean isArray(): determines if this Class object represents an array class.
3) public boolean isPrimitive(): determines if the specified Class object represents a primitive type.
Let's see the simple example of reflection api to determine the object type.
  1. class Simple{}  
  2. interface My{}  
  3.   
  4. class Test{  
  5.  public static void main(String args[]){  
  6.   try{  
  7.    Class c=Class.forName("Simple");  
  8.    System.out.println(c.isInterface());  
  9.      
  10.    Class c2=Class.forName("My");  
  11.    System.out.println(c2.isInterface());  
  12.     
  13.   }catch(Exception e){System.out.println(e);}  
  14.   
  15.  }  
  16. }  

Drawbacks,

  • You lose compile-time type safety - it's helpful to have the compiler verify that a method is available at compile time. If you are using reflection, you'll get an error at runtime which might affect end users if you don't test well enough. Even if you do catch the error, it will be be more difficult to debug.
  • It causes bugs when refactoring - if you are accessing a member based on its name (e.g. using a hard-coded string) then this won't get changed by most code refactoring tools and you'll instantly have a bug, which might be quite hard to track down.
  • Performance is slower - reflection at runtime is going to be slower than statically compiled method calls/variable lookups. If you're only doing reflection occasionally then it won't matter, but this can become a performance bottleneck in cases where you are making calls via reflection thousands or millions of times per second. I once got a 10x speedup in some Clojure code simply by eliminating all reflection, so yes, this is a real issue.

No comments:

Post a Comment