Reflection in Java with Examples

In this Java article, we are going to discuss Reflection in Java. Here, we will learn what Java Reflection is and how we can utilize it to get data. We will also look at the advantages and drawbacks of Reflection in Java.

Then we will discuss various methods of the Class that are used in Reflection. Finally we will understand each concept with the sample code using Reflection in Java and Java reflection class.

What is Reflection in Java?

Reflection in Java is an API(Application Programming Interface) that is used at runtime to analyze or change classes, methods, and interfaces. It is a process of examining or modifying the run time behavior of a class at run time.

The java.lang.Class is a class that provides many methods that we can use to get metadata of the class and to examine and change the runtime behavior of a class. There are two packages- java.lang and java.lang.reflect that provide classes for Java Reflection.

Some points about Reflection in Java are:

  • The classes required for reflection in Java are present in the java.lang.reflect package.
  • Reflection gives us data about the class with the associated objects and the methods for that class.
  • Through reflection, we can call a method at runtime independent of their access specifier.

Java Reflection

Where Reflection is used?

The Reflection API of Java is mainly used in:

  • Integrated Development Environment(IDEs) such as Eclipse, MyEclipse, NetBeans, etc.
  • Debugger
  • Test Tools

java.lang.Class class

The java.lang.The class performs two essential tasks:

  • It provides methods to get the metadata of a class at runtime.
  • It provides methods to examine and change the behavior of the class at runtime.

Commonly used methods of the Class class:

Method Description
public String getName() returns the name of the class.
public static Class forName(String className) This method loads the class and returns the reference of Class.
public Object newInstance() It creates a new object of the class.
public boolean isInterface() This method checks if it is an interface.
public boolean isArray() This method checks if it is an array.
public boolean isPrimitive() This method checks if it is primitive.
public Class getSuperclass() It returns the superclass or parent class reference.
public Field[] getDeclaredFields() It returns the total number of fields in the class.
public Method[] getDeclaredMethods() It returns the total number of methods of the class.
public Method getDeclaredMethod(String name,Class[] parameterTypes) This method returns the method class instance.
public Constructor[] getDeclaredConstructors() It returns the total number of constructors of this class.

How can we get the object of Class class?

There are three ways to get the object of Class class. They are:

  • forName() method of Class class.
  • getClass() method of Object class.
  • the .class syntax.

We will discuss each of the methods with an example:

1) The forName() method of Class class

The forName() method loads the class dynamically or at runtime. This method returns the instance of Class class. We should use it only if we know the fully qualified name of the class. We cannot use this name for primitive types.
Let’s see the example of forName() method to get the instance of the class:

class Demo {}
class Test {
  public static void main(String args[]) {
    try {
      Class c = Class.forName("Demo");
      System.out.println(c.getName());
    }
    catch(Exception e) {
      System.out.println(e);
    }
  }
}

Output:

Demo

2) The getClass() method of Object class

The getClass() method belongs to the Object class and it returns the instance of Class class. We should use it when we know the type. We can also use it with primitives.

Let us see the example:

class Demo {}
class Test {
  void printName(Object obj) {
    Class c = obj.getClass();
    System.out.println(c.getName());
  }
  public static void main(String args[]) {
    Demo obj = new Demo();
    Test t = new Test();
    t.printName(obj);
  }
}

Output:

Demo

3) The .class syntax

Sometimes, there is a situation when a type is available but there is no instance of the class. In such cases, we can obtain the Class by appending the .class syntax to the name of the type. We can also use this syntax with primitives.

Let us see its example:

class Demo {
  public static void main(String args[]) {
    Class c1 = boolean.class;
    System.out.println(c1.getName());

    Class c2 = Demo.class;
    System.out.println(c2.getName());
  }
}

Output:

boolean
Demo

Example of Reflection API to determine the type of object

Let’s see the simple example of the reflection API to determine the object type.

class Demo {}

interface MyInterface {}

class Test {
  public static void main(String args[]) {
    try {
      Class c = Class.forName("Demo");
      System.out.println(c.isInterface());

      Class c2 = Class.forName("MyInterface");
      System.out.println(c2.isInterface());

    }
    catch(Exception e) {
      System.out.println(e);
    }
  }
}

Output:

false
true

Getting Information using Reflection API

Java reflection api

We can use Reflection to get the information about:

1. Class: The getClass() method gives the name of the class to which an object belongs.

2. Constructors: The getConstructors() method returns all the public constructors of the class to which an object belongs.

3. Methods: The getMethods() method gives all the public methods of the class to which an object belongs.

Code:

import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
class ReflectionDemo {
  private String str;
  public ReflectionDemo() {
    str = "Techvidvan Java Tutorial";
  }
  public void method1() {
    System.out.println("\nThe string is: " + str);
  }
  public void method2(int num1) {
    System.out.println("\nThe number is: " + num1);
  }
  private void method3() {
    System.out.println("\nprivate method invoked");
  }
}
public class Test {
  public static void main(String args[]) {
    ReflectionDemo obj = new ReflectionDemo();
    Class cls = obj.getClass();
    System.out.println("\nThe name of the class is: " + cls.getName());

    Constructor constructor = cls.getConstructor();
    System.out.println("\nThe name of the constructor is: " + constructor.getName());

    System.out.println("\nThe public methods of the class are: ");
    Method[] methods = cls.getMethods();

    for (Method method: methods)
    System.out.println(method.getName());

    Method methodCall1 = cls.getDeclaredMethod("method2", int.class);
    methodCall1.invoke(obj, 35);
    Field field = cls.getDeclaredField("str");
    field.setAccessible(true);
    field.set(obj, "Java");
    Method methodCall2 = cls.getDeclaredMethod("method1");
    methodCall2.invoke(obj);
    Method methodCall3 = cls.getDeclaredMethod("method3");
    methodCall3.setAccessible(true);
    methodCall3.invoke(obj);
  }
}

Output:

The name of the class is: ReflectionDemo
The name of the constructor is: ReflectionDemo
The public methods of the class are:
method2
method1
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
The number is: 35
The string is: Java
private method invoked

Getting Interfaces

We can use the getInterfaces() method of Class to get the information about the interfaces implemented by the class. The getInterfaces() method returns an array of interfaces.

Example:

import java.lang.Class;
import java.lang.reflect. * ;

interface Bike {
  public void display();
}

interface Bicycle {
  public void makeNoise();
}

class TwoWheeler implements Bike,
Bicycle {
  public void display() {
    System.out.println("I am a bike");
  }

  public void makeNoise() {
    System.out.println("I make noise");
  }
}

class ReflectionDemo {
  public static void main(String[] args) {
    try {
      //create an object of TwoWheeler class
      TwoWheeler t = new TwoWheeler();

      //create an object of Class using getClass()
      Class obj = t.getClass();

      //find the interfaces implemented by TwoWheeler
      Class[] objInterface = obj.getInterfaces();
      for (Class c: objInterface) {
        //print the name of interfaces
        System.out.println("Interface Name: " + c.getName());
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
}

Output:

Interface Name: Bike
Interface Name: Bicycle

Getting Superclass and Access Modifier in Java

We can use the getSuperclass() method of the class Class to get information about the superclass of a particular class. The Class class also provides a method getModifier() that returns the access modifier of class in integer form.

Example:

import java.lang.Class;
import java.lang.reflect. * ;

interface Person {
  public void display();
}

public class Student implements Person {
  public void display() {
    System.out.println("I am a student.");
  }
}

class ReflectionDemo {
  public static void main(String[] args) {
    try {
      //create an object of Student class
      Student s1 = new Student();

      //create an object of Class using getClass()
      Class obj = s1.getClass();

      //Get the access modifier of Student in integer form
      int modifier = obj.getModifiers();
      System.out.println("Access Modifier: " + Modifier.toString(modifier));

      //Find the superclass of Student
      Class superClass = obj.getSuperclass();
      System.out.println("Superclass: " + superClass.getName());
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
}

Output:

Access Modifier: public
Superclass: java.lang.Object

Advantages of using Java Reflection

1. Extensibility Features: Reflection allows an application to use user-defined and external classes by creating instances of extensible objects using their fully-qualified names.

2. Debugging and testing tools: Debuggers make use of the property of reflection to detect the private members of a class.

Disadvantages of using Java Reflection

1. Performance Overhead: The performance of operations of Reflection is slower than the non-reflective operations. We should avoid the use of reflection in sections of code that we call frequently in performance-sensitive applications.

2. Exposure of Internals: Reflective code violates the concept of abstraction and therefore there may be a change in the behavior with upgrades of the platform.

Important Observations about Reflection in Java

1. We can invoke a method through reflection if we know its name and parameter types. We use two methods for this purpose

a. getDeclaredMethod(): To create an object of the method to be invoked.
The syntax for this method is:

Class.getDeclaredMethod(name, parametertype)

name- The name of a method whose object is to be created
parametertype- parameter is an array of Class objects

b. invoke() method: To invoke a method of the class at runtime we use the following method:

Method.invoke(Object, parameter)

If the method of the class doesn’t accept any parameter then null is passed as an argument.

2. We can access the private methods and variables of a class using Reflection. We can access them using its class object, and invoke the method by using the object as discussed above. Two methods are there for this purpose. These methods are:

a. Class.getDeclaredField(FieldName): Returns the private field of the class. It returns an object of type Field for the specified field name.

b. Field.setAccessible(true): Allows accessing the field irrespective of the access modifier used with the field.

Conclusion

Hence, in this article, we completely understood the concept of reflection in Java. Moreover, we also discussed classes and methods used for reflection in Java. Along with this, we also discussed the advantages and disadvantages of Java Reflection. We learned how to get the name of the class, interfaces, methods, and constructors of the class. We can easily get the data about the class using the reflection API.