Java Reflection: A Basic Introduction

java reflectionReflection is one of the most advanced features of any dynamic language like C# or Java that enables developers to perform delicate operations. It’s used to inspect and modify runtime behavior of objects in an application, which means that it analyzes the structure of code and enables the programmer to change its expected behavior. In Java Reflection, only an examining feature is available, but it’s possible to change the accessibility of fields and methods.

To learn more about Java essentials, take a course at Udemy.com

What is Java Reflection?

Java Reflection is the set of classes and interfaces packed in a ‘java.lang.reflect’ that provides the following functionalities:

  • To inspect the class, use an interface and enum and retrieve their structures at runtime.
  • To get information about fields and methods at runtime.
  • To instantiate an object, invoke its methods and change the field values at runtime without any prior knowledge of its implementation.

How to use Java Reflection?

Java Reflection is a very powerful feature, but in case if there is any alternative solution exists for a problem, it is preferable to avoid using this feature. Therefore, before any implementation of Java Reflection, you should keep the following issues in mind:

  • Reflection doesn’t fully support Java Virtual Machine (JVM) optimization, since Java Reflection involves dynamically resolved types that reduce the performance of code.
  • Security restrictions are different from each other, which may result in an unexpected outcome with the same Java Reflection code.
  • Non-reflection code perspective about some operation like accessing the private fields are illegal, so Java Reflection’s implementation of such operation may affect the portability of code.

The following example demonstrates the use of basic Java Reflection operations for retrieving the class name from object of that class.

Code snippet (Book Class):

package BookStore;
public class Book {
public String name;
public String version;
private String yearOfPublish;
public Book(){
}
public Book (String name,String version, String yearOfPublish){
this.name=name;
this.version=version;
this.yearOfPublish = yearOfPublish;
}
public void setYearOfPublish (String yearOfPublish){
this.yearOfPublish = yearOfPublish;
}
public String getYearOfPublish (){
returnthis.yearOfPublish;
}
public void print() {
System.out.println ("Name: " + this.name + " Version " + this.version);
} private void privatePrint() {

System.out.println ("Name: " + this.name + " Version " + this.version + " Published in "+ this.yearOfPublish);

} }

Code snippet (ReflectionExample Class):

import BookStore.Book;
public class ReflectionExample {
public static void main (String[] args) throws Exception {
Book sampleBook = new Book ("Java Reflection", "1.0", "2014");
System.out.println (sampleBook.getClass ().getName ());
//BookStore.Book } }

In the above code snippet, the ‘getClass’ inherited method returns the runtime class of the Book object as a ‘Method’ object. An instance method ‘getName’ of ‘Method’ class in Java Reflection package, is called to return the name as a string of the ‘Method’ object.

Interested in learning more about Java? Take a look at a Udemy.com course

Java Reflection for Classes

The starting point of every Java Reflection operation is the ‘java.lang.Class’ class instance which represents the classes and interfaces in the Java application. Java Virtual Machine creates an immutable instance of a ‘Class’ which provides the methods to analyze the runtime behavior of an object like creation, invoking methods, runtime properties of an object.

The following code snippet demonstrates the use of Java Reflection to retrieve the fields, methods and constructors of a ‘Book’ class.

Code snippet:

Field [] pbFields = Class.forName ("BookStore.Book"). getFields ();
System.out.println (Arrays.toString (pbFields));
Method [] pbMethods = Class. forName ("BookStore.Book"). getMethods ();

System.out.println (Arrays.toString (pbMethods));
Constructor<?> [] pbConstructors = Class. forName ("BookStore.Book"). getConstructors ();
System.out.println (Arrays.toString (pbConstructors));

 

There are several possible ways to instantiate the class using Java Reflection. Most common of those are  via the ‘newInstance’ method of ‘Class’ and ‘newInstance’ method of ‘Constructor’ object.

Code Snippet (using ‘newInstance’ method of ‘Class’):

Class <?> c = null;
c = Class.forName ("BookStore.Book");

Book newBook = null;
newBook = (Book) c.newInstance ();
name = "Java Reflection";
version = "1.0";
newBook.setYearOfPublish ("2014"); newBook.print ();

 

Code snippet (using ‘newInstance’ method of ‘Constructor’)

Class <?> c = null;
c = Class.forName ("BookStore.Book");
Book newBook = null;
Constructor <?> cons [] = c.getConstructors ();
newBook = (Book) cons[1]. newInstance ("Java Reflection","1.0","2014");
newBook.print ();

In the above code snippet, in first example of Java Reflection ‘fromName’ method returns the book ‘Class’ object which uses the ‘newInstance’ method to instantiates the class and cast it to ‘Book’, in this case empty constructor of ‘Book’ is called to create an object.

In the second example the resultant book ‘Class’ object retrieve all the constructors of ‘Book’ class by calling the ‘getConstructors’ method and assigned it to the ‘Constructor’ object array. Using this object array a book constructor with three parameters is called to instantiates the ‘Book’ class.

Java Reflection for Fields

Java Reflection provides some methods to examine the Class fields and change their values at runtime. Using Java Reflection, it is possible to set and get the value of a field. Following examples provide the basic get and set operations on public and private field using Java Reflection.

Code snippet (Get and Set the public field)    

Field field = Class.forName ("BookStore.Book").getField ("version");

Book sampleBook = new Book ("Java Reflection", "1.0", "2014");
System.out.println (field.get (sampleBook)); //prints 1.0
field.set (sampleBook, "1.1");
System.out.println (field.get (sampleBook)); //prints 1.1

Code snippet (Get and Set the private field)

Field private Field = Class.forName ("BookStore.Book").getDeclaredField ("yearOfPublish"); privateField.setAccessible (true); Book sampleBook = new Book ("Java Reflection", "1.0", "2014");
System.out.println (privateField.get (sampleBook)); //prints 2014
private Field.set (sampleBook, "2013");
System.out.println (privateField.get (sampleBook)); //prints 2013

Java Reflection for Methods

Through, Java Reflection, it is possible to get all the methods of a Class and invoke the public as well as private methods using the ‘Method’ object.

Code snippet (Invoke the public method)

Method method;
Book sampleBook = new Book ("Java Reflection", "1.0", "2014");
method = sampleBook.getClass().getMethod("print", new Class<?>[0]);
method.invoke(sampleBook);

Code snippet (Invoke the private method)

Method method;
Book sampleBook = new Book ("Java Reflection", "1.0", "2014");
method = sampleBook.getClass().getDeclaredMethod ("privatePrint", new Class<?>[0]);
method.setAccessible (true);
method.invoke (sampleBook);

In the above code snippet, the code uses the Class object and finds out if the object has a method called “print” or in case of private method ‘privatePrint’ using ‘getMethod’ and ‘getDeclaredMethod’ respectively. Finally, ‘invoke’ is called on ‘Method’ object with ‘Book’ object as an argument.

For more detailed Java tutorials, take a course at Udemy.com.