Recent Posts

Friday, 13 May 2016

Java Reflection Tutorial

     Java Reflection is the process of analyzing and modifying all the capabilities of a particular class at runtime. Reflection API in Java is used to manipulate class and its members which include fields, methods, constructor, etc. at runtime. One advantage of reflection API in Java is, it can manipulate private members of the class too. The java.lang.reflect package provides many classes to implement reflection java. Methods of the java.lang.Class class is used to gather the complete metadata of a particular class.
Internal details of a class or interface: 
1.  Finding the name of the package in which class or interface presents.
2.  Finding whether the .class file is class definition or interface definition.
3.  Finding Modifiers (Public, abstract, final) of a class or a interface.
4.  Finding the name of the base class for the current class.
5.  Finding the name of the base interface for the current class.
6.  Finding the number of data members in a class.
7.  Finding number of constructors in a class.
8.  Finding number of methods in a class.
9.  Finding the number of data members in an interface.
10. Finding number of methods in an interface.
11. Finding the names of the base interfaces for the current interface.
12. Finding logical/simple name of class name and interface name.

     Following is a list of various Java classes in java.lang.package to implement reflection-
1. java.lang.reflect.Field: This class is used to gather declarative information such as datatype, access modifier, name and value of a variable.
2. java.lang.reflect.Method: This class is used to gather declarative information such as access modifiers, return type, name, parameter types and exception type of a method.
3. java.lang.reflect.Constructor: This class is used to gather declarative information such as access modifier, name and parameter types of a constructor.
4. java.lang.reflect.Modifier: This class is used to gather information about a particular access modifier.

Purpose of java.lang.Class
     The main purpose of java.lang.Class is to gather the complete meta data of a particular class.

How to get complete information about a class
     To get information about variables, methods, and constructors of a class, we need to create an object of the class. There are three ways to create object 

1) Using Class.forName()
1. It is used to load the class dynamically.
2. Returns the instance of Class class.
3. 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.
class Employee {}   

class Test {   
   public static void main (String args[]){   
      Class clazz = Class.forName("com.ashok.reflection.Employee");   
   }   
}
2) Using getClass() method
     It returns the instance of Class class. It should be used if you know the type. Moreover, it can be used with primitives.
class Employee {}   

class Test {   
   public static void main (String args[]){   
      Employee emp = new Employee (); 
      Class clazz = emp.getClass(); 
   }   
} 
3) Using 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.
class Employee {}  

class Test {   
   public static void main (String args[]){   
       Class clazz = Employee.class;    
   }  
} 
Example
package com.ashok.reflection; 

import java.io.Serializable; 

public class Employee implements Serializable, Cloneable { 
    private static final long serialVersionUID = 1L; 
    public int empId; 
    public static String empName; 
    public String empAddress; 
    public Employee () { 

    } 

    public Employee(int empId, String empName, String empAddress) { 
        this.empId = empId; 
        this.empName = empName; 
        this.empAddress = empAddress; 
    } 

    public void addEmployee(int empId, String empName, 
                              String empAddress) { 
        this.empId = empId; 
        this.empName = empName; 
        this.empAddress = empAddress; 
    } 

    public void searchEmployee(int empId) { 
        // search logic to get employee object using empId 
    } 

    public int getEmpId() throws Exception { 
        return empId; 
    } 

    public void setEmpId(int empId) { 
        this.empId = empId; 
    } 

    public static String getEmpName() { 
        return empName; 
    } 

    public static void setEmpName(String empName) { 
        Employee.empName = empName; 
    } 

    public String getEmpAddress() { 
        return empAddress; 
    } 

    public void setEmpAddress(String empAddress) { 
        this.empAddress = empAddress; 
    } 
} 
1. Get Metadata of Class
     Following example shows how to get metadata such as: Class name, super class name, implemented interfaces, and access modifiers of a class. 
E.g
package com.ashok.reflection; 

import java.lang.reflect.Modifier; 

public class ClassMetaData { 
    public static void main (String [] args) { 
        Class clazz = Employee.class; 
        System.out.println("Class Name is: " +clazz.getName()); 
        System.out.println("Super Class Name is: " 
                      +clazz.getSuperclass().getName()); 
        Class [] interfaces = clazz.getInterfaces(); 
        System.out.println("Implemented interfaces are "); 
        for(Class interf : interfaces) { 
            System.out.println(interf.getName()); 
        } 
        System.out.println("Access modifiers are: " 
                      +Modifier.toString(clazz.getModifiers())); 
    } 
} 

Output 
Class Name is : com.ashok.reflection.Employee 
Super Class Name is : java.lang.Object 
Implemented interfaces are  
java.io.Serializable 
java.lang.Cloneable 
Access modifiers are: public 
2. Get Metadata of Variable 
    To get the metadata in the form of field array using getFields() or getDeclaredFields() methods  
1. getFields() method returns metadata of the public variable from the specified class as well as from its super class.

2. getDeclaredFields() method returns metadata of the all the variables from the specified class only.
package com.ashok.reflection; 

import java.lang.reflect.Field; 
import java.lang.reflect.Modifier; 

public class VariableMetaData { 
    public static void main (String [] args) throws Exception { 
        Class clazz = Employee.class; 
        Field [] fields= clazz.getDeclaredFields(); 
        for (Field field: fields) {  
            System.out.println("Variable name: "+field.getName()); 
            System.out.println("Datatypes of the variable:"
                                +field.getType()); 
            System.out.println("Access Modifiers of the variable: "
                              +Modifier.toString(field.getModifiers())); 
            System.out.println("-------------------------------------"); 
        } 
    } 
} 

Output 
Variable name: serialVersionUID 
Datatypes of the variable:long 
Access Modifiers of the variable: private static final 
-------------------------------------------------- 
Variable name: empId 
Datatypes of the variable:int 
Access Modifiers of the variable: public 
-------------------------------------------------- 
Variable name: empName 
Datatypes of the variable:class java.lang.String 
Access Modifiers of the variable: public static 
-------------------------------------------------- 
Variable name: empAddress 
Datatypes of the variable:class java.lang.String 
Access Modifiers of the variable: public 
3. Get Metadata of Method
     To get the metadata in the form of method array using getMethods() or getDeclaredMethods() methods  
1. getMethods() method returns metadata of the public methods from the specified class as well as from its super class.
2. getDeclaredMethods() method returns metadata of the all the methods from the specified class only.
package com.ashok.reflection; 

import java.lang.reflect.Method; 
import java.lang.reflect.Modifier; 

public class MethodMetaData { 
    public static void main(String[] args) { 
       Class clazz = Employee.class; 
       Method[] methods = clazz.getDeclaredMethods(); 
       for (Method method : methods) { 
           System.out.println("Name of the method: " + method.getName()); 
           System.out.println("Return type of the method: " 
                               + method.getReturnType()); 
           System.out.println("Method access modifiers: " 
                               + Modifier.toString(method.getModifiers())); 

           Class[] paramList = method.getParameterTypes(); 
           for (Class cls : paramList) { 
               System.out.println(cls.getName() + " "); 
           } 
           System.out.println(); 

           Class [] exceptionList = method.getExceptionTypes(); 
           System.out.println("Excpetion thrown by method:"); 
           for (Class cls : exceptionList) { 
              System.out.println(cls.getName() + " "); 
           } 
           System.out.println("---------------------------------"); 
       } 
    } 
} 

Output 
Name of the method: addEmployee 
Return type of the method: void 
Method access modifiers: public 
Method parameter types: 
int  
java.lang.String  
java.lang.String  
Excpetion thrown by method: 
--------------------------------------------------- 
Name of the method: setEmpId 
Return type of the method: void 
Method access modifiers: public 
Method parameter types: 
int  
Excpetion thrown by method: 
--------------------------------------------------- 
Name of the method: getEmpId 
Return type of the method: int 
Method access modifiers: public 
Method parameter types: 
Excpetion thrown by method: 
java.lang.Exception  
--------------------------------------------------- 
Name of the method: setEmpAddress 
Return type of the method: void 
Method access modifiers: public 
Method parameter types: 
java.lang.String  
Excpetion thrown by method: 
--------------------------------------------------- 
Name of the method: setEmpName 
Return type of the method: void 
Method access modifiers: public static 
Method parameter types: 
java.lang.String  
Excpetion thrown by method: 
--------------------------------------------------- 
Name of the method: getEmpAddress 
Return type of the method: class java.lang.String 
Method access modifiers: public 
Method parameter types: 
Excpetion thrown by method: 
--------------------------------------------------- 
Name of the method: getEmpName 
Return type of the method: class java.lang.String 
Method access modifiers: public static 
Method parameter types: 
Excpetion thrown by method: 
--------------------------------------------------- 
Name of the method: searchEmployee 
Return type of the method: void 
Method access modifiers: public 
Method parameter types: 
int  
Excpetion thrown by method: 
--------------------------------------------------
4. Get Metadata of Constructors
package com.ashok.reflection; 
  
import java.lang.reflect.Constructor; 
import java.lang.reflect.Modifier; 

public class ConstructorMetaData { 
    public static void main(String[] args) { 
        Class clazz = Employee.class; 
        Constructor[] constructorList = clazz.getConstructors();     

        for (Constructor constructor: constructorList) { 
            System.out.println("Constrcutor name: "+constructor.getName());          
            System.out.println("Constrctor modifier: "
                              +Modifier.toString(constructor.getModifiers())); 
            Class[] paramList=constructor.getParameterTypes(); 
            System.out.println("Constrctor parameter types :");  
            for (Class class1: paramList) {  
               System.out.println(class1.getName() +" "); 
            } 
            System. out.println();  

            Class[] exceptionList=constructor.getExceptionTypes(); 
            System.out.println("Exception thrown by constructors:");  
            for (Class class1: exceptionList) {  
                System.out.println(class1.getName() +" "); 
            }  
            System.out.println("--------------------------------------"); 
        } 
    } 
} 

Output 
Constrcutor name: com.ashok.reflection.Employee 
Constrctor modifier: public 
Constrctor parameter types: 
Exception thrown by constructors: 
------------------------------------------ 
Constrcutor name: com.ashok.reflection.Employee 
Constrctor modifier: public 
Constrctor parameter types: 
int  
java.lang.String  
java.lang.String   
Exception thrown by constructors: 
------------------------------------------ 
5. Getter and Setter Methods
package com.ashok.reflection;  

import java.lang.reflect.Method; 

public class GetterAndSetter { 
    public static void main(String[] args) { 
        Class clazz = Employee.class;  
        Method[] methods = clazz.getDeclaredMethods(); 
        for (Method method : methods) { 
            if (isGetter(method)) 
                System.out.println("Getter: " + method); 
    
            if (isSetter(method)) 
                System.out.println("Setter: " + method); 
        } 
    }  

    public static boolean isGetter(Method method) { 
        if (!method.getName().startsWith("get") && 
                method.getParameterTypes().length != 0 
                && void.class.equals(method.getReturnType())) 
            return false; 
        return true; 
    } 

    public static boolean isSetter(Method method) { 
        if (!method.getName().startsWith("set") && 
                method.getParameterTypes().length != 1) 
            return false; 
        return true; 
    } 
} 
Setter: public void com.ashok.reflection.Employee.setEmpId(int)
Setter: public void com.ashok.reflection.Employee.setEmpAddress
         (java.lang.String)
Setter: public static void com.ashok.reflection.Employee.setEmpName
         (java.lang.String)
Getter: public int com.ashok.reflection.Employee.getEmpId() throws 
          java.lang.Exception
Getter: public java.lang.String com.ashok.reflection.Employee.
          getEmpAddress()
Getter: public static java.lang.String com.ashok.reflection.Employee.
          getEmpName()
Invoke methods
package com.ashok.reflection; 
public class Employee { 
    public int empId; 
    public static String empName; 
    public String empAddress; 

    public void addEmployee(int empId, String empName, String empAddress) { 
        this.empId = empId; 
        this.empName = empName; 
        this.empAddress = empAddress; 
        System.out.println("Inside addEmployee"); 
    } 

    private void getPrivateData() { 
        System.out.println("Inside private data"); 
    } 

    public static void getStaticData() { 
        System.out.println("Inside Static data"); 
    } 
} 

package com.ashok.reflection; 
import java.lang.reflect.Method; 
public class MethodInvoke { 
    public static void main(String[] args) throws Exception { 
        Class clazz = Employee.class; 
        Method method = clazz.getDeclaredMethod("addEmployee",int.class, String.class, String.class); 
        method.invoke(Employee.class.newInstance(), 87,"Ashok","Bhimavaram"); 

        // Invoke private method 
        Method privateMethod = clazz.getDeclaredMethod("getPrivateData"); 
        privateMethod.setAccessible(true); 
        privateMethod.invoke(Employee.class.newInstance()); 

        // Invoke Static method 
        Method staticMethod = clazz.getDeclaredMethod("getStaticData"); 
        staticMethod.invoke(null); 
    } 
} 

Output 
Inside addEmployee 
Inside private data 
Inside Static data 
Get annotations at runtime using reflection 
     Annotations allow us to provide metadata (data about data) information into our source code. More about annotations refer here
package com.ashok.reflection; 

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation { 
    public String key(); 
    public String value(); 
} 

package com.ashok.reflection; 

import java.lang.reflect.Method; 

public class MyAnnotationTest { 
    @MyAnnotation(key="website", value="https://www.waytoeasylearn.com") 
    public void myAnnotationMethod(){ 
        try { 
            Class cls = this.getClass(); 
            Method method = cls.getMethod("myAnnotationMethod"); 
            MyAnnotation myAnno = method.getAnnotation(MyAnnotation.class); 
            System.out.println("Key is: "+myAnno.key()); 
            System.out.println("Value is: "+myAnno.value()); 
        } catch (SecurityException e) { 
            e.printStackTrace(); 
        } catch (NoSuchMethodException e) { 
            e.printStackTrace(); 
        } 
    } 

    public static void main(String a[]){ 
        MyAnnotationTest mat = new MyAnnotationTest(); 
        mat.myAnnotationMethod(); 
    } 
}
Key is:  website
Value is: https://www.waytoeasylearn.com

     That's it guys. This is all about Java Reflection Tutorial. Let me know your comments and suggestions about this tutorial. Thank you.

No comments:

Post a Comment