Introduction To Reflection | Part 1

I've always been curious about Java Reflection but never took the time to dive into it — until now. Recently, I decided to finally explore this powerful feature in depth and picked a couple of solid resources to guide me along the way: 1. The Reflection API – dev.java 2. Learn Reflection with Java by Dr. Heinz M. Kabutz (O’Reilly) In this blog series ,I’ll share what I’ve learned, highlight key takeaways, and include practical examples to help you understand how Reflection works and when (or when not) to use it. What is Reflection? Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible. Source: https://dev.java/learn/reflection/intro Why learn reflection? Using reflection in Java is like using a painkiller It's a bit too strong for everyday use. But it can relieve severe pain. We Can discover what class an object is Once we know, we can Call method Read and write fields Construct new instance Usefulness of Reflection Frameworks DI(Dependency Injection), Data Serialization, Dynamic Configuration Serialization ObjectOutputStream.writeObject() uses reflection extensively Dangers Of Reflection reflection can make code harder to understand static code tools do not work anymore 1.Using Reflection on Class Each Object in java knows its class We can find out what it is with Object.getClass() getClass() returns the actual Object type, not the declaration Who has a class? Every Type in java has a representative class Even primitive type,interface, enums, annutations insted of getClass() , we can use .class What is a Type of Class? class is a generic class, defined as class objects generic type parameters are erased at compile time int.class and Integer.class are both type of class But they are not the same object Name Of Class getName() Oldest Method, write Strange output for arrays Integer.class.getName() return java.lang.Integer getSimpleName() Strips away the package name Integer.class.getSimpleName() return Integer getCanonicalName() Full Class name, better array output, null for unknown type Integer.class.getCanonicalName() return java.lang.Integer getTypeName() Full Class name, better array output, never null "introduced in java 8" Integer.class.getTypeName() return java.lang.Integer getPackageName() Package in which class resides,java.lang for primitives "introduced in java 9" Integer.class.getPackageName() return java.lang Using Class.forName() it is possible to get the corresponding Class using the static method Class.forName() Class.forName() has three forms: forName(String className) most simple, all that is needed is the full class name forName(String className, boolean initialize, ClassLoader loader) most useful - we can avoid initializing until we need it and specify another class loader forName(Module module , String name) java 9 support for modules All forName() method return a Class forName() method cannot be used for primitive types, but can be used for any array, including arrays of primitive types. // Get Class object for String[] Class stringArrayClass = Class.forName("[Ljava.lang.String;"); call class with forName() method: Class c = Class.forName("java.lang.String"); This code return the class object of string. If this class does not exist, this method throws a ClassNotFoundException. Using Class.forPrimitiveName() A method Class.forPrimitiveName() was added to the class Class in Java SE 22. This method returns the corresponding class for any primitive type, including void. Class c = Class.forPrimitiveName("int"); System.out.println("class: " + c); //class: int What is a ReflectiveOperationException When you work with reflection, several exceptions may occur. To handle this,We use ReflectiveOperationException class. ReflectiveOperationException has 6 subclasses: ClassNotFoundException - class.forName() did not resolve IllegalAccessException - trying to access a private memeber InstantiationException - trying to instantiate an abstract type NoSuchFieldException - field by that name not found NoSuchMethodException - method/constructor not found InvocationTargetException - wrapper for another exception public static void main(String[] args) throws ReflectiveOperationException { Class arrayListClass = (Class) Class.forName(ArrayList.class.getTypeName()); System.out.prin

Apr 13, 2025 - 11:00
 0
Introduction To Reflection | Part 1

Introduction To Reflection

I've always been curious about Java Reflection but never took the time to dive into it — until now. Recently, I decided to finally explore this powerful feature in depth and picked a couple of solid resources to guide me along the way:

1. The Reflection API – dev.java
2. Learn Reflection with Java by Dr. Heinz M. Kabutz (O’Reilly)

In this blog series ,I’ll share what I’ve learned, highlight key takeaways, and include practical examples to help you understand how Reflection works and when (or when not) to use it.

What is Reflection?

Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible.
Source: https://dev.java/learn/reflection/intro

Why learn reflection?

  • Using reflection in Java is like using a painkiller
    • It's a bit too strong for everyday use.
    • But it can relieve severe pain.
  • We Can discover what class an object is
  • Once we know, we can
    • Call method
    • Read and write fields
    • Construct new instance

Usefulness of Reflection

  • Frameworks
    • DI(Dependency Injection), Data Serialization, Dynamic Configuration
  • Serialization
    • ObjectOutputStream.writeObject() uses reflection extensively

Dangers Of Reflection

  • reflection can make code harder to understand
  • static code tools do not work anymore

1.Using Reflection on Class

Each Object in java knows its class

  • We can find out what it is with Object.getClass()
  • getClass() returns the actual Object type, not the declaration

Who has a class?

  • Every Type in java has a representative class
    • Even primitive type,interface, enums, annutations
    • insted of getClass() , we can use .class

What is a Type of Class?

  • class is a generic class, defined as class
    • objects generic type parameters are erased at compile time
    • int.class and Integer.class are both type of class But they are not the same object

Name Of Class

  • getName()

    • Oldest Method, write Strange output for arrays
    • Integer.class.getName() return java.lang.Integer
  • getSimpleName()

    • Strips away the package name
    • Integer.class.getSimpleName() return Integer
  • getCanonicalName()

    • Full Class name, better array output, null for unknown type
    • Integer.class.getCanonicalName() return java.lang.Integer
  • getTypeName()

    • Full Class name, better array output, never null "introduced in java 8"
    • Integer.class.getTypeName() return java.lang.Integer
  • getPackageName()

    • Package in which class resides,java.lang for primitives "introduced in java 9"
    • Integer.class.getPackageName() return java.lang

Using Class.forName()

it is possible to get the corresponding Class using the static method Class.forName()

Class.forName() has three forms:

  • forName(String className)
    • most simple, all that is needed is the full class name
  • forName(String className, boolean initialize, ClassLoader loader)
    • most useful - we can avoid initializing until we need it and specify another class loader
  • forName(Module module , String name)
    • java 9 support for modules

All forName() method return a Class
forName() method cannot be used for primitive types, but can be used for any array, including arrays of primitive types.

 // Get Class object for String[]
 Class stringArrayClass = Class.forName("[Ljava.lang.String;");

call class with forName() method:

Class c = Class.forName("java.lang.String");

This code return the class object of string. If this class does not exist, this method throws a ClassNotFoundException.

Using Class.forPrimitiveName()

A method Class.forPrimitiveName() was added to the class Class in Java SE 22. This method returns the corresponding class for any primitive type, including void.

Class c = Class.forPrimitiveName("int");
System.out.println("class: " + c); //class: int

What is a ReflectiveOperationException

When you work with reflection, several exceptions may occur. To handle this,We use ReflectiveOperationException class.

ReflectiveOperationException has 6 subclasses:

  • ClassNotFoundException - class.forName() did not resolve
  • IllegalAccessException - trying to access a private memeber
  • InstantiationException - trying to instantiate an abstract type
  • NoSuchFieldException - field by that name not found
  • NoSuchMethodException - method/constructor not found
  • InvocationTargetException - wrapper for another exception
public static void main(String[] args) 
throws ReflectiveOperationException {

     Class<ArrayList> arrayListClass = 
     (Class<ArrayList>) Class.forName(ArrayList.class.getTypeName());

     System.out.println(arrayListClass.getName());
}

Know the super type of Class.forName()

The asSubclass() method is used to cast a Class to a more specific Class, with type safety checked at runtime.

It ensures that the class represented by the Class object is actually a subclass (or same class) of the given clazz, otherwise it throws a ClassCastException

import java.util.*;

public class ListReflectionExample {
    public static void main(String[] args) throws Exception {

      // Load the class dynamically
      Class rawClass = Class.forName(ArrayList.class.getTypeName());

        // Ensure it's a subclass of List
        Class extends List> listClass = rawClass.asSubclass(List.class);

        // Create an instance using the no-arg constructor
        List<String> list = listClass.getDeclaredConstructor().newInstance();

        // Use the list like normal
        list.add("Reflection");
        list.add("is");
        list.add("cool!");

        System.out.println(String.join(" ", list));
    }
}

Better way of loading unknown class

Class.forName(String) calls all the static initializers

  • This happens before asSubclass can check the type
  • Better is to load the class uninitialized
    • it will be initialized before we use it for the first time

By default loaded into the current class loader

  • Better to use Thread.currentThread().getContextClassLoader()
    • Allows frameworks to inject different class loaders
public class ClassForNameWithContextLoader {
    public static void main(String[] args) throws Exception {
        // Get the context class loader of the current thread
        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        System.out.println("Loading class with initialize = false...");
        Class clazz1 = Class.forName("MyStaticClass", false, loader);
        System.out.println("Class loaded: " + clazz1.getName());

        System.out.println("\nNow loading with initialize = true...");
        Class clazz2 = Class.forName("MyStaticClass", true, loader);
        System.out.println("Class loaded and initialized: " + clazz2.getName());
    }
}

Tip: Use Thread.currentThread().getContextClassLoader() when loading classes in environments where multiple class loaders are involved — like in application servers, Spring Boot, or plugin systems. It helps avoid ClassNotFoundException when the default loader can’t see certain classes

In next part we check method, modifiers, Constructor, nested class, sealed class and record