What is Reflection?
Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time. It is also possible to instantiate new objects, invoke methods and get/set field values using reflection. That means with reflection, we can examine or modify the runtime behavior of applications running in the Java virtual machine.
Reflection API usage can break the design pattern such as Singleton pattern by invoking the private constructor i.e violating the rules of access modifiers.
Difference between Introspection and Reflection?
Introspection is the ability of a program to examine the type or properties of an object at runtime. Where as, Reflection is the ability of a program to examine and modify the structure and behavior of an object at runtime.
Introspection is a subset of reflection. Some of the languages support introspection, but do not support reflection, e.g., C++.
Introspection Example:
The instanceof operator determines whether an object belongs to a particular class.
if(obj instanceof Account){
Account acc = (Account)obj;
acc.getBalance();
}
Reflection Example:
The Class.forName() method returns the Class object associated with the class/interface with the given name(a string and full qualified name). The forName method causes the class with the name to be initialized.
Class c = Class.forName("classpath.classname");
Object acc = c.newInstance();
Method m = c.getDeclaredMethod("getBalance", new Class[0]);
m.invoke(acc);
Why do we need Reflection?
What are the various Java classes in java.lang.package?
How to get the object of Class class?
There are 3 ways to get the instance of Class class:
forName() method of Class class:
e.g:
Class c=Class.forName("MyEmployee");
System.out.println(c.getName());
getClass() method of Object class
e.g:
void printName(Object obj){
Class c=obj.getClass();
System.out.println(c.getName());
}
.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.
e.g:
Class c = boolean.class;
System.out.println(c.getName());
Commonly used methods of Class class:
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 use reflection?
Lets define a Printer class.
package mytest;
class Printer {
public void print() {
System.out.println("printing..");
}
}
Get class name from object
package mytest;
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Printer p = new Printer();
System.out.println("PackageName.ClassName is " + p.getClass().getName());
}
}
Invoke method on unknown object: By using reflection, the code can use the object and find out if the object has a method called "print" and then call it.
package mytest;
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Printer p = new Printer();
Method method;
try {
method = p.getClass().getMethod("print", new Class[0]);
method.invoke(p); //this will call print() method
} catch (Exception e) {
e.printStackTrace();
}
}
}
Create object from Class instanceThere are 3 ways to get the instance of Class class. They are as follows:
1. forName() method of Class class
2. getClass() method of Object class
3. the .class syntax
package mytest;
public class ReflectionHelloWorld {
public static void main(String[] args){
Class c = null; //create instance of "Class"
try{
c=Class.forName("mytest.Printer");
}catch(Exception e){
e.printStackTrace();
}
Printer p = null;
try {
p = (Printer) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
p.print();
}
}
Get constructor and create instance: Lets define a constructor in Printer class.
package mytest;
class Printer {
String name;
public Printer(){}
public Printer(String name){
this.name=name;
}
public void print() {
System.out.println("printing.."+ name);
}
}
package mytest;
import java.lang.reflect.Constructor;
public class ReflectionHelloWorld {
public static void main(String[] args){
Class c = null;
try{
c=Class.forName("mytest.Printer");
}catch(Exception e){
e.printStackTrace();
}
Printer p1 = null;
Printer p2 = null;
//it will return all constructors
Constructor cons[] = c.getConstructors();
try {
p1 = (Printer) cons[0].newInstance();
p2 = (Printer) cons[1].newInstance("testprinter");
} catch (Exception e) {
e.printStackTrace();
}
p1.print();
p2.print();
}
}Output will be
printing..null
printing..testprinter
Can we access private field and method using Reflection?
Yes we can. Private fields and methods are only accessible in the class they are declared but with reflection you can call private method and access private fields outside the class (which is not possible by any other means in Java).
How to access private fields in Java using Reflection?
In order to access private field using reflection, you need to know the name of field than by calling getDeclaredFields(String name) you will get a java.lang.reflect.Field instance representing that field.
Remember: Use getDeclaredFields() method and not getFields() because the later returns all non private fields both from sub class and super class. While getDeclaredFields() returns both private and non private fields declared in the class.
Once you get the field reference you need to make it accessible by calling Field.setAccessible(true) because you are going to access private field. Now you can get value or private field by calling Field.get(String field_name). If you don't call setAccessible(true) and try to access the private field using reflection you will get below Exception:
java.lang.IllegalAccessException: Class test.ReflectionTest can not access a member of class test.Person with modifiers "private"
How to call private methods in Java using Reflection?
As we have mentioned above (in 'Invoke method on unknown object' section) that we can call a method by its String name and then using the invoke() method. In similar way we can invoke the private methods.
Use getDeclaredMethods(String name, Class.. parameter) to get declared private method. Pass all the argument type needed by method or nothing if method doesn't accept any argument. This will give you instance of java.lang.reflect.Method which can than be used to call private method using reflection, as shown in below example:
Make changes in Printer class:
package mytest;
class Printer {
private String name;
public String printerid;
public Printer(){}
public Printer(String name, String printerid){
this.name=name;
this.printerid=printerid;
}
private void print() {
System.out.println("printing.."+ name);
}
}
package mytest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ReflectionTest {
public static void main(String args[]) throws ClassNotFoundException {
Class printer = (Class) Class.forName("mytest.Printer");
System.out.println("Private Fields: " + Arrays.toString(printer.getFields()));
System.out.println("All Fields : " + Arrays.toString(printer.getDeclaredFields()));
System.out.println("Declared methods : " + Arrays.toString(printer.getDeclaredMethods()));
try {
//accessing value of private field
Printer privatePrint = new Printer("PrinterOne" , "1");
Field privateField = printer.getDeclaredField("name");
privateField.setAccessible(true);
String value = (String) privateField.get(privatePrint);
System.out.println("Private field: " + privateField + ", value: " + value);
//accessing private method using reflection
Method privateMethod = printer.getDeclaredMethod("print");
privateMethod.setAccessible(true);
privateMethod.invoke(privatePrint);
}
catch (InvocationTargetException ex) {}
catch (NoSuchMethodException ex) {}
catch (IllegalArgumentException ex) {}
catch (IllegalAccessException ex) {}
catch (NoSuchFieldException ex) {}
catch (SecurityException ex) {}
}
}
What are some practical uses of Java reflection?
One of the more common uses of Java reflection is with JUnit, which is a popular unit testing framework for Java. One commonly used feature of JUnit uses annotations to mark certain methods as test methods that which are meant to help you test your Java code. Then, when you actually decide to run your unit tests, JUnit will look for the methods which you marked with the “@Test” annotation, and will execute those methods.
-K Himaanshu Shuklaa...
Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time. It is also possible to instantiate new objects, invoke methods and get/set field values using reflection. That means with reflection, we can examine or modify the runtime behavior of applications running in the Java virtual machine.
Reflection API usage can break the design pattern such as Singleton pattern by invoking the private constructor i.e violating the rules of access modifiers.
Difference between Introspection and Reflection?
Introspection is the ability of a program to examine the type or properties of an object at runtime. Where as, Reflection is the ability of a program to examine and modify the structure and behavior of an object at runtime.
Introspection is a subset of reflection. Some of the languages support introspection, but do not support reflection, e.g., C++.
Introspection Example:
The instanceof operator determines whether an object belongs to a particular class.
if(obj instanceof Account){
Account acc = (Account)obj;
acc.getBalance();
}
Reflection Example:
The Class.forName() method returns the Class object associated with the class/interface with the given name(a string and full qualified name). The forName method causes the class with the name to be initialized.
Class c = Class.forName("classpath.classname");
Object acc = c.newInstance();
Method m = c.getDeclaredMethod("getBalance", new Class[0]);
m.invoke(acc);
Why do we need Reflection?
- Examine an object's class at runtime
- Construct an object for a class at runtime
- Examine a class's field and method at runtime
- Invoke any method of an object at runtime
- Change accessibility flag of Constructor, Method and Field etc.
- IDE (Integrated Development Environment) e.g. Eclipse, MyEclipse, NetBeans etc.
- Debugger
- Test Tools. For example, JUnit use reflection to look through methods tagged with the @Test annotation, and then call those methods when running the unit test.
- Spring framework uses dependency injection (DI) to populate the dependencies into beans defined in config files. DI framework actually heavily uses reflection for injecting these bean dependencies.
What are the various Java classes in java.lang.package?
- Field: This class is used to gather declarative information such as datatype, access modifier, name and value of a variable.
- Method: This class is used to gather declarative information such as access modifier, return type, name, parameter types and exception type of a method.
- Constructor: This class is used to gather declarative information such as access modifier, name and parameter types of a constructor.
- Modifier: This class is used to gather information about a particular access modifier.
How to get the object of Class class?
There are 3 ways to get the instance of Class class:
- forName() method of Class class
- getClass() method of Object class
- the .class syntax.
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.
- cannot be used for primitive types.
e.g:
Class c=Class.forName("MyEmployee");
System.out.println(c.getName());
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.
e.g:
void printName(Object obj){
Class c=obj.getClass();
System.out.println(c.getName());
}
.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.
e.g:
Class c = boolean.class;
System.out.println(c.getName());
Commonly used methods of Class class:
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 use reflection?
Lets define a Printer class.
package mytest;
class Printer {
public void print() {
System.out.println("printing..");
}
}
Get class name from object
package mytest;
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Printer p = new Printer();
System.out.println("PackageName.ClassName is " + p.getClass().getName());
}
}
Invoke method on unknown object: By using reflection, the code can use the object and find out if the object has a method called "print" and then call it.
package mytest;
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Printer p = new Printer();
Method method;
try {
method = p.getClass().getMethod("print", new Class[0]);
method.invoke(p); //this will call print() method
} catch (Exception e) {
e.printStackTrace();
}
}
}
Create object from Class instanceThere are 3 ways to get the instance of Class class. They are as follows:
1. forName() method of Class class
2. getClass() method of Object class
3. the .class syntax
package mytest;
public class ReflectionHelloWorld {
public static void main(String[] args){
Class c = null; //create instance of "Class"
try{
c=Class.forName("mytest.Printer");
}catch(Exception e){
e.printStackTrace();
}
Printer p = null;
try {
p = (Printer) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
p.print();
}
}
Get constructor and create instance: Lets define a constructor in Printer class.
package mytest;
class Printer {
String name;
public Printer(){}
public Printer(String name){
this.name=name;
}
public void print() {
System.out.println("printing.."+ name);
}
}
package mytest;
import java.lang.reflect.Constructor;
public class ReflectionHelloWorld {
public static void main(String[] args){
Class c = null;
try{
c=Class.forName("mytest.Printer");
}catch(Exception e){
e.printStackTrace();
}
Printer p1 = null;
Printer p2 = null;
//it will return all constructors
Constructor cons[] = c.getConstructors();
try {
p1 = (Printer) cons[0].newInstance();
p2 = (Printer) cons[1].newInstance("testprinter");
} catch (Exception e) {
e.printStackTrace();
}
p1.print();
p2.print();
}
}Output will be
printing..null
printing..testprinter
Can we access private field and method using Reflection?
Yes we can. Private fields and methods are only accessible in the class they are declared but with reflection you can call private method and access private fields outside the class (which is not possible by any other means in Java).
How to access private fields in Java using Reflection?
In order to access private field using reflection, you need to know the name of field than by calling getDeclaredFields(String name) you will get a java.lang.reflect.Field instance representing that field.
Remember: Use getDeclaredFields() method and not getFields() because the later returns all non private fields both from sub class and super class. While getDeclaredFields() returns both private and non private fields declared in the class.
Once you get the field reference you need to make it accessible by calling Field.setAccessible(true) because you are going to access private field. Now you can get value or private field by calling Field.get(String field_name). If you don't call setAccessible(true) and try to access the private field using reflection you will get below Exception:
java.lang.IllegalAccessException: Class test.ReflectionTest can not access a member of class test.Person with modifiers "private"
How to call private methods in Java using Reflection?
As we have mentioned above (in 'Invoke method on unknown object' section) that we can call a method by its String name and then using the invoke() method. In similar way we can invoke the private methods.
Use getDeclaredMethods(String name, Class.. parameter) to get declared private method. Pass all the argument type needed by method or nothing if method doesn't accept any argument. This will give you instance of java.lang.reflect.Method which can than be used to call private method using reflection, as shown in below example:
Make changes in Printer class:
package mytest;
class Printer {
private String name;
public String printerid;
public Printer(){}
public Printer(String name, String printerid){
this.name=name;
this.printerid=printerid;
}
private void print() {
System.out.println("printing.."+ name);
}
}
package mytest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ReflectionTest {
public static void main(String args[]) throws ClassNotFoundException {
Class
System.out.println("Private Fields: " + Arrays.toString(printer.getFields()));
System.out.println("All Fields : " + Arrays.toString(printer.getDeclaredFields()));
System.out.println("Declared methods : " + Arrays.toString(printer.getDeclaredMethods()));
try {
//accessing value of private field
Printer privatePrint = new Printer("PrinterOne" , "1");
Field privateField = printer.getDeclaredField("name");
privateField.setAccessible(true);
String value = (String) privateField.get(privatePrint);
System.out.println("Private field: " + privateField + ", value: " + value);
//accessing private method using reflection
Method privateMethod = printer.getDeclaredMethod("print");
privateMethod.setAccessible(true);
privateMethod.invoke(privatePrint);
}
catch (InvocationTargetException ex) {}
catch (NoSuchMethodException ex) {}
catch (IllegalArgumentException ex) {}
catch (IllegalAccessException ex) {}
catch (NoSuchFieldException ex) {}
catch (SecurityException ex) {}
}
}
What are some practical uses of Java reflection?
One of the more common uses of Java reflection is with JUnit, which is a popular unit testing framework for Java. One commonly used feature of JUnit uses annotations to mark certain methods as test methods that which are meant to help you test your Java code. Then, when you actually decide to run your unit tests, JUnit will look for the methods which you marked with the “@Test” annotation, and will execute those methods.
-K Himaanshu Shuklaa...
No comments:
Post a Comment