CodeToConcept
About

java

java Tutorials

Introduction
Java Variables
Java Data Types
Java Type Casting
Java Operators
Java Input/Output
Java Class & Object
java Method
Java Constructor
Java this keyword
Java super keyword
Java Method Overloading and Overriding
Java Interface
Java Abstract Class
Java Memory Management
Design Patterns
JDBC (Database Connectivity)
Java IDEs

java Tutorials

Introduction
Java Variables
Java Data Types
Java Type Casting
Java Operators
Java Input/Output
Java Class & Object
java Method
Java Constructor
Java this keyword
Java super keyword
Java Method Overloading and Overriding
Java Interface
Java Abstract Class
Java Memory Management
Design Patterns
JDBC (Database Connectivity)
Java IDEs

Sample Question

Think it through, then check the tutorial.

CodeToConcept

Quickly learn through simple, structured, and practical coding tutorials. Build your confidence from step zero to real-world experience.

© 2026 CodeToConcept. All rights reserved.

Quick Links

AboutTutorials

Tutorials

JavaHTMLCSS

Support

Privacy PolicyTerms of ServiceContact
GitHubTwitterYouTube

Java Reflection API

Run each complete program separately. Its required helper classes and imports are included in the same code block. Short syntax fragments explain individual operations.

Reflection lets code inspect types, fields, constructors, and methods through runtime metadata. It can help tools work with classes they do not name directly in source. Access rules, module boundaries, and failure handling still apply.

Normally, Java code knows the class and its members at compile time.

For example:

Student student = new Student();
student.display();

Here, the compiler already knows about the Student class and its display() method.

With Reflection, a program can discover information about the Student class while the program is running.

For example, it can find:

  • Class name
  • Package name
  • Superclass
  • Interfaces
  • Fields
  • Methods
  • Constructors
  • Modifiers
  • Annotations

Reflection can also be used to dynamically access members when appropriate.

1. What is Reflection?

Reflection is a Java feature that allows a program to inspect and interact with classes and objects at runtime.

The Reflection API is mainly available through the:

java.lang.reflect

package.

Some important classes and interfaces are:

Class
Field
Method
Constructor
Modifier

The Class class is especially important because it provides information about a class at runtime.

2. Why Do We Need Reflection?

Normally, Java programs are strongly connected to classes known at compile time.

For example:

Student student = new Student();

But sometimes an application does not know the exact class it needs to work with until runtime.

Reflection can be useful in situations such as:

  • Framework development
  • Dependency injection
  • Testing frameworks
  • Object mapping
  • Serialization libraries
  • Plugin systems
  • Annotation processing at runtime
  • Development tools
  • Debugging tools

Many frameworks use reflection or related runtime mechanisms to discover classes and their members.

3. The Class Class

The most important starting point for Reflection is the Class class.

Every Java class has a corresponding Class object that contains metadata about that class.

For example:

Class<?> clazz = Student.class;

The Class object can then be used to inspect the Student class.

4. Getting a Class Object

There are several common ways to obtain a Class object.

Method 1: Using .class

Class<?> clazz = Student.class;

Method 2: Using getClass()

If an object already exists:

Student student = new Student();
 
Class<?> clazz = student.getClass();

Method 3: Using Class.forName()

A class can also be loaded using its fully qualified name.

Class<?> clazz = Class.forName("com.example.Student");

This approach is useful when the class name is available as a string at runtime.

5. Simple Reflection Example

Consider the following class:

class Student {
 
    int id;
    String name;
 
    void display() {
        System.out.println("Student information");
    }
}

Now inspect it using Reflection.

class Student {
 
    int id;
    String name;
 
    void display() {
        System.out.println("Student information");
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<?> clazz = Student.class;
 
        System.out.println("Class Name: " + clazz.getName());
    }
}

Output

Class Name: Student

6. getName()

The getName() method returns the fully qualified name of the class.

For example:

Class<?> clazz = Student.class;
 
System.out.println(clazz.getName());

If the class belongs to a package:

package com.example;
 
class Student {
}

the result can be:

com.example.Student

7. getSimpleName()

The getSimpleName() method returns only the class name without the package.

Class<?> clazz = Student.class;
 
System.out.println(clazz.getSimpleName());

Output

Student

8. getPackageName()

The package name can be obtained using:

clazz.getPackageName();

For example:

Class<?> clazz = Student.class;
 
System.out.println(clazz.getPackageName());

If the class is in:

package com.example;

the output is:

com.example

9. Inspecting the Class Modifiers

The getModifiers() method returns the modifiers associated with a class. This complete program inspects its own public HelloWorld class.

import java.lang.reflect.Modifier;
 
public class HelloWorld {
    public static void main(String[] args) {
        int modifiers = HelloWorld.class.getModifiers();
        System.out.println(Modifier.toString(modifiers));
    }
}

Output:

public

10. Inspecting the Superclass

The getSuperclass() method returns the direct superclass.

Example

class Person {
}
 
class Student extends Person {
}

Now:

class Person {
}
 
class Student extends Person {
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<?> clazz = Student.class;
 
        Class<?> parent = clazz.getSuperclass();
 
        System.out.println(parent.getSimpleName());
    }
}

Output

Person

11. Inspecting Interfaces

The getInterfaces() method returns the interfaces directly implemented by a class.

Example

interface Printable {
}
 
interface Exportable {
}
 
class Report implements Printable, Exportable {
}

Reflection:

interface Printable {
}
 
interface Exportable {
}
 
class Report implements Printable, Exportable {
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<?> clazz = Report.class;
 
        Class<?>[] interfaces = clazz.getInterfaces();
 
        for (Class<?> type : interfaces) {
            System.out.println(type.getSimpleName());
        }
    }
}

Output

Printable
Exportable

12. Getting All Declared Fields

The getDeclaredFields() method returns the fields declared directly inside a class.

Example

class Student {
 
    private int id;
    String name;
    public double marks;
}

Reflection:

import java.lang.reflect.Field;
class Student {
 
    private int id;
    String name;
    public double marks;
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<?> clazz = Student.class;
 
        Field[] fields = clazz.getDeclaredFields();
 
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }
}

Output

id
name
marks

13. Getting Field Type

The Field object provides information about a field.

For example:

field.getType()

Example

import java.lang.reflect.Field;
class Student {
 
    private int id;
    String name;
    public double marks;
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<?> clazz = Student.class;
 
        Field[] fields = clazz.getDeclaredFields();
 
        for (Field field : fields) {
 
            System.out.println(
                    field.getName() +
                    " : " +
                    field.getType().getSimpleName()
            );
        }
    }
}

Output

id : int
name : String
marks : double

14. Getting Field Modifiers

We can also inspect whether a field is:

  • private
  • public
  • static
  • final
  • etc.

Example

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
class Student {
 
    private int id;
    String name;
    public double marks;
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<?> clazz = Student.class;
 
        Field[] fields = clazz.getDeclaredFields();
 
        for (Field field : fields) {
 
            System.out.println(
                    Modifier.toString(field.getModifiers())
                    + " "
                    + field.getName()
            );
        }
    }
}

15. getFields() vs getDeclaredFields()

This is an important distinction.

getFields()

Returns accessible public fields, including inherited public fields.

Field[] fields = clazz.getFields();

getDeclaredFields()

Returns fields declared directly in the class, including private fields.

Field[] fields = clazz.getDeclaredFields();
MethodFields Returned
getFields()Public fields, including inherited public fields
getDeclaredFields()Fields declared directly in the class

16. Getting a Specific Field

Instead of retrieving all fields, we can retrieve one field by name.

Field field = clazz.getDeclaredField("name");

Example

import java.lang.reflect.Field;
class Student {
 
    private int id;
    String name;
    public double marks;
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws NoSuchFieldException {
 
        Class<?> clazz = Student.class;
 
        Field field = clazz.getDeclaredField("name");
 
        System.out.println(field.getName());
        System.out.println(field.getType().getSimpleName());
    }
}

Output

name
String

17. Reading a Field Value

Reflection can also be used to read a field from an object.

Consider:

class Student {
 
    String name = "Rahul";
}

We can read the value using Field.get().

import java.lang.reflect.Field;
class Student {
 
    String name = "Rahul";
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws Exception {
 
        Student student = new Student();
 
        Field field =
                Student.class.getDeclaredField("name");
 
        Object value = field.get(student);
 
        System.out.println(value);
    }
}

Output

Rahul

18. Setting a Field Value

Reflection can also modify a field value when access is permitted.

import java.lang.reflect.Field;
class Student {
 
    String name = "Rahul";
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws Exception {
 
        Student student = new Student();
 
        Field field =
                Student.class.getDeclaredField("name");
 
        field.set(student, "Amit");
 
        System.out.println(student.name);
    }
}

Output

Amit

19. Accessing a Private Field

Consider:

class Student {
 
    private String name = "Rahul";
}

A private field is not normally directly accessible outside its class.

Reflection provides APIs for working with declared members, but access to private members is subject to Java's access-control rules and runtime/module boundaries.

For example, code may use:

Field field =
        Student.class.getDeclaredField("name");

In contexts where access is permitted, reflective access can be enabled using:

field.setAccessible(true);

Then:

Object value = field.get(student);

can access the field.

However, setAccessible(true) should not be treated as a general way to bypass security boundaries. Modern Java's module system and strong encapsulation can restrict reflective access.

20. Getting Methods

The Method class represents a method.

Import it using:

import java.lang.reflect.Method;

To get all declared methods:

Method[] methods =
        clazz.getDeclaredMethods();

Example

import java.lang.reflect.Method;
 
class Student {
 
    void display() {
    }
 
    void calculateMarks() {
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<?> clazz = Student.class;
 
        Method[] methods =
                clazz.getDeclaredMethods();
 
        for (Method method : methods) {
            System.out.println(method.getName());
        }
    }
}

Output

display
calculateMarks

The exact order of reflection results should not be relied upon.

21. Getting Method Information

A Method object provides information such as:

  • Method name
  • Return type
  • Parameters
  • Modifiers
  • Declaring class

Example

import java.lang.reflect.Method;
 
class Calculator {
 
    public int add(int a, int b) {
        return a + b;
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Method[] methods =
                Calculator.class.getDeclaredMethods();
 
        for (Method method : methods) {
 
            System.out.println(
                    "Method: " + method.getName()
            );
 
            System.out.println(
                    "Return Type: " +
                    method.getReturnType().getSimpleName()
            );
        }
    }
}

Output

Method: add
Return Type: int

22. Getting Method Parameters

The getParameterTypes() method returns the parameter types of a method.

Example

import java.lang.reflect.Method;
 
class Calculator {
 
    public int add(int a, int b) {
        return a + b;
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws Exception {
 
        Method method =
                Calculator.class.getDeclaredMethod(
                        "add",
                        int.class,
                        int.class
                );
 
        Class<?>[] parameters =
                method.getParameterTypes();
 
        for (Class<?> parameter : parameters) {
            System.out.println(
                    parameter.getSimpleName()
            );
        }
    }
}

Output

int
int

23. Invoking a Method Using Reflection

One of the important features of Reflection is dynamically invoking a method.

Consider:

class Calculator {
 
    public int add(int a, int b) {
        return a + b;
    }
}

We can invoke add() using Reflection.

import java.lang.reflect.Method;
class Calculator {
 
    public int add(int a, int b) {
        return a + b;
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws Exception {
 
        Calculator calculator =
                new Calculator();
 
        Method method =
                Calculator.class.getDeclaredMethod(
                        "add",
                        int.class,
                        int.class
                );
 
        Object result =
                method.invoke(calculator, 10, 20);
 
        System.out.println(result);
    }
}

Output

30

24. Understanding Method.invoke()

The basic syntax is:

method.invoke(object, arguments);

For example:

method.invoke(calculator, 10, 20);

Here:

  • method represents the method to invoke.
  • calculator is the object on which the method is called.
  • 10 and 20 are the method arguments.

25. Invoking a Method Without Arguments

Consider:

class Student {
 
    public void display() {
        System.out.println("Student information");
    }
}

Reflection:

Method method =
        Student.class.getDeclaredMethod("display");
 
method.invoke(student);

Output

Student information

26. Getting Constructors

The Constructor class represents a constructor.

Import:

import java.lang.reflect.Constructor;

To get all declared constructors:

Constructor<?>[] constructors =
        clazz.getDeclaredConstructors();

Example

import java.lang.reflect.Constructor;
 
class Student {
 
    Student() {
    }
 
    Student(int id) {
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Constructor<?>[] constructors =
                Student.class.getDeclaredConstructors();
 
        for (Constructor<?> constructor : constructors) {
            System.out.println(
                    constructor.getName()
            );
        }
    }
}

Possible output:

Student
Student

27. Creating an Object Using Reflection

A constructor can be obtained and invoked dynamically.

Example

import java.lang.reflect.Constructor;
 
class Student {
 
    int id;
    String name;
 
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws Exception {
 
        Constructor<Student> constructor =
                Student.class.getConstructor(
                        int.class,
                        String.class
                );
 
        Student student =
                constructor.newInstance(
                        101,
                        "Rahul"
                );
 
        System.out.println(student.id);
        System.out.println(student.name);
    }
}

Output

101
Rahul

This creates an object without directly writing:

new Student(101, "Rahul");

28. getConstructor() vs getDeclaredConstructor()

getConstructor()

Finds a public constructor.

Constructor<?> constructor =
        clazz.getConstructor();

getDeclaredConstructor()

Finds a constructor declared by the class, including non-public constructors subject to access restrictions.

Constructor<?> constructor =
        clazz.getDeclaredConstructor();

29. Getting All Constructors

Constructor<?>[] constructors =
        Student.class.getDeclaredConstructors();
 
for (Constructor<?> constructor : constructors) {
 
    System.out.println(
            constructor.getName()
    );
}

You can also inspect constructor parameters:

Class<?>[] parameters =
        constructor.getParameterTypes();

30. Inspecting Modifiers

A class can have several modifiers. This program declares HelloWorld as both public and final, then reads those modifiers.

import java.lang.reflect.Modifier;
 
public final class HelloWorld {
    public static void main(String[] args) {
        int modifiers = HelloWorld.class.getModifiers();
        System.out.println(Modifier.toString(modifiers));
    }
}

Output:

public final

31. Checking Specific Modifiers

You can check whether a member is public, private, static, final, etc.

For example:

Modifier.isPublic(modifiers)

or:

Modifier.isPrivate(modifiers)

or:

Modifier.isStatic(modifiers)

Example

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
 
class Student {
 
    private static final int MAX_MARKS = 100;
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws Exception {
 
        Field field =
                Student.class.getDeclaredField(
                        "MAX_MARKS"
                );
 
        int modifiers =
                field.getModifiers();
 
        System.out.println(
                Modifier.isPrivate(modifiers)
        );
 
        System.out.println(
                Modifier.isStatic(modifiers)
        );
 
        System.out.println(
                Modifier.isFinal(modifiers)
        );
    }
}

Output

true
true
true

32. Reflection and Inheritance

Reflection provides different methods for declared and inherited members.

For example:

getDeclaredMethods()

returns methods declared directly in the class.

Whereas:

getMethods()

returns public methods, including inherited public methods.

Similarly:

getDeclaredFields()

and:

getFields()

have different behavior.

33. getMethods() vs getDeclaredMethods()

MethodMeaning
getMethods()Public methods, including inherited public methods
getDeclaredMethods()Methods declared directly in the class

For example:

Method[] methods =
        Student.class.getMethods();

and:

Method[] methods =
        Student.class.getDeclaredMethods();

should not be considered interchangeable.

34. Annotations and Reflection

Reflection can also be used to inspect annotations at runtime.

Consider:

@Retention(RetentionPolicy.RUNTIME)
@interface Info {
 
    String value();
}

Then:

@Info("Student class")
class Student {
}

Reflection can inspect the annotation.

Example

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
 
@Retention(RetentionPolicy.RUNTIME)
@interface Info {
 
    String value();
}
 
@Info("Student class")
class Student {
}
 
public class HelloWorld {
 
    public static void main(String[] args) {
 
        Class<Student> clazz =
                Student.class;
 
        Info info =
                clazz.getAnnotation(Info.class);
 
        System.out.println(info.value());
    }
}

Output

Student class

The annotation must have runtime retention for this particular runtime reflection example.

35. Reflection and Generic Types

Reflection can also provide information about generic declarations.

For example:

import java.lang.reflect.Field;
import java.util.List;
 
class Student {
 
    List<String> names;
}

We can inspect the generic type:

Field field =
        Student.class.getDeclaredField("names");
 
System.out.println(
        field.getGenericType()
);

Possible output:

java.util.List<java.lang.String>

This can be useful for frameworks that need information about generic declarations.

36. Complete Reflection Example

The following example demonstrates several Reflection API features together.

import java.lang.reflect.*;
 
class Student {
 
    private int id;
    private String name;
 
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
 
    public void display() {
        System.out.println(
                "Student: " + id + " - " + name
        );
    }
}
 
public class HelloWorld {
 
    public static void main(String[] args)
            throws Exception {
 
        Class<?> clazz =
                Student.class;
 
        // Class information
        System.out.println(
                "Class: " + clazz.getSimpleName()
        );
 
        // Fields
        System.out.println("\nFields:");
 
        for (Field field :
                clazz.getDeclaredFields()) {
 
            System.out.println(
                    field.getName()
                    + " : "
                    + field.getType().getSimpleName()
            );
        }
 
        // Constructors
        System.out.println("\nConstructors:");
 
        for (Constructor<?> constructor :
                clazz.getDeclaredConstructors()) {
 
            System.out.println(
                    constructor.getName()
            );
        }
 
        // Methods
        System.out.println("\nMethods:");
 
        for (Method method :
                clazz.getDeclaredMethods()) {
 
            System.out.println(
                    method.getName()
            );
        }
 
        // Create object
        Constructor<?> constructor =
                clazz.getConstructor(
                        int.class,
                        String.class
                );
 
        Object student =
                constructor.newInstance(
                        101,
                        "Rahul"
                );
 
        // Invoke method
        Method method =
                clazz.getDeclaredMethod(
                        "display"
                );
 
        method.invoke(student);
    }
}

Possible Output

Class: Student
 
Fields:
id : int
name : String
 
Constructors:
Student
 
Methods:
display
 
Student: 101 - Rahul

The order of reflection results such as fields and methods should not be relied upon.

37. Practical Example: Dynamic Class Loading

Suppose the class name is provided as a string.

String className = "java.util.ArrayList";
 
Class<?> clazz =
        Class.forName(className);
 
System.out.println(
        clazz.getName()
);

Output

java.util.ArrayList

This is useful when the class to load is determined dynamically.

38. Practical Example: Creating an Object Dynamically

Consider a class:

class Student {
 
    public Student() {
        System.out.println(
                "Student object created"
        );
    }
}

We can load and instantiate it dynamically.

Class<?> clazz =
        Class.forName("Student");
 
Object object =
        clazz.getDeclaredConstructor()
             .newInstance();

Output

Student object created

The class name could instead come from configuration or another runtime source.

39. Where Reflection Is Used

Reflection is commonly encountered in:

Frameworks

Frameworks can inspect classes and discover their fields, methods, constructors, and annotations.

Dependency Injection

A framework may inspect a class and determine which dependencies need to be provided.

Testing

Testing frameworks can discover test methods based on annotations or naming/configuration conventions.

Object Mapping

Libraries can inspect fields and constructors when converting between objects and data representations.

Plugin Systems

Applications can load and inspect classes dynamically.

Development Tools

IDEs and debugging tools can inspect classes and objects.

40. Advantages of Reflection

1. Dynamic Behavior

Classes can be inspected at runtime.

2. Framework Development

Reflection is useful when building general-purpose frameworks.

3. Runtime Class Discovery

Applications can work with classes whose exact details are not hard-coded.

4. Annotation Processing

Runtime annotations can be inspected and interpreted.

5. Flexible Object Creation

Constructors can be discovered and invoked dynamically.

41. Disadvantages of Reflection

Reflection is powerful, but it also has trade-offs.

1. Reduced Compile-Time Safety

Normal code:

student.display();

is checked by the compiler.

Reflection:

method.invoke(student);

moves some errors to runtime.

2. More Complex Code

Reflection usually requires more code than normal Java programming.

3. Runtime Exceptions

Incorrect class names, method names, parameter types, or access conditions can cause runtime exceptions.

Examples include:

ClassNotFoundException
NoSuchMethodException
NoSuchFieldException
IllegalAccessException
InvocationTargetException

4. Performance Considerations

Reflective operations can have additional overhead compared with direct method or field access.

For performance-sensitive code, direct calls are generally preferable when the members are already known.

5. Access Restrictions

Modern Java strongly enforces encapsulation and module boundaries. Reflective access to non-public members may be restricted depending on the runtime and module configuration.

42. Common Reflection Exceptions

ExceptionMeaning
ClassNotFoundExceptionRequested class could not be found
NoSuchMethodExceptionRequested method/constructor was not found
NoSuchFieldExceptionRequested field was not found
IllegalAccessExceptionAccess to a member was not permitted
InstantiationExceptionObject creation could not be performed through the attempted API
InvocationTargetExceptionInvoked method/constructor threw an exception
SecurityExceptionA security restriction prevented the operation

43. Common Mistakes

Mistake 1: Wrong Class Name

Class.forName("Student");

works only when the class can be resolved with that name from the current class-loading context.

For a packaged class, use the fully qualified name:

Class.forName("com.example.Student");

Mistake 2: Wrong Method Parameters

Suppose:

int add(int a, int b)

Then:

getDeclaredMethod(
    "add",
    int.class,
    int.class
);

is required to identify that overload.

Calling it with incorrect parameter types can result in NoSuchMethodException.

Mistake 3: Confusing getMethods() and getDeclaredMethods()

Remember:

getMethods()

focuses on public methods, including inherited public methods.

While:

getDeclaredMethods()

returns methods declared directly in the class.

Mistake 4: Assuming Reflection Always Bypasses Access Restrictions

Reflection does not mean that every private or strongly encapsulated member can always be accessed.

Modern Java access and module rules can prevent reflective access.

Mistake 5: Ignoring InvocationTargetException

When a method invoked through Reflection throws an exception, the reflective call can report it through:

InvocationTargetException

The underlying exception can be inspected through its cause.

44. Reflection API Important Classes

ClassPurpose
ClassProvides runtime information about a class
FieldRepresents a field
MethodRepresents a method
ConstructorRepresents a constructor
ModifierProvides modifier information
ParameterRepresents a method or constructor parameter

These classes are mainly found in:

java.lang.reflect

45. Reflection API Important Methods

Class Information

getName()
getSimpleName()
getPackageName()
getSuperclass()
getInterfaces()
getModifiers()

Fields

getFields()
getDeclaredFields()
getField()
getDeclaredField()

Methods

getMethods()
getDeclaredMethods()
getMethod()
getDeclaredMethod()

Constructors

getConstructors()
getDeclaredConstructors()
getConstructor()
getDeclaredConstructor()

Dynamic Operations

Field.get()
Field.set()
Method.invoke()
Constructor.newInstance()

46. Reflection vs Normal Java Code

Normal JavaReflection
Class known at compile timeClass can be inspected at runtime
Direct method callsMethods can be discovered dynamically
Direct field accessFields can be inspected dynamically
Compiler catches many errorsMore errors can occur at runtime
Usually simplerUsually more complex
Generally easier to optimizeMay have additional runtime overhead

47. Reflection and Encapsulation

Java's encapsulation allows a class to control access to its internal state.

For example:

class Student {
 
    private int marks;
}

Normally, code outside the class cannot directly access:

student.marks;

Reflection provides APIs for inspecting declared members, but reflective access to private members is governed by Java's access-control and module rules.

Therefore, Reflection should not be used simply to avoid good object-oriented design.

Prefer normal public methods such as:

student.getMarks();

when a class intentionally exposes that behavior.

48. When Should You Use Reflection?

Reflection is appropriate when the application genuinely needs runtime inspection or dynamic behavior.

Good use cases include:

  • Framework infrastructure
  • Generic libraries
  • Runtime annotation processing
  • Plugin architectures
  • Testing infrastructure
  • Dynamic class discovery

Avoid Reflection when ordinary Java code can solve the problem clearly.

For example, prefer:

student.display();

over Reflection when the class and method are already known.

49. Reflection API Flow

A typical Reflection operation can be understood as:

Get Class
   |
   v
Inspect Metadata
   |
   +----> Fields
   |
   +----> Methods
   |
   +----> Constructors
   |
   +----> Annotations
   |
   v
Perform Dynamic Operation
   |
   +----> Read Field
   |
   +----> Set Field
   |
   +----> Invoke Method
   |
   +----> Create Object

50. Key Points to Remember

  1. Reflection allows Java programs to inspect classes at runtime.
  2. The Class class is the main entry point to Reflection.
  3. A Class object can be obtained using .class, getClass(), or Class.forName().
  4. Field represents a class field.
  5. Method represents a method.
  6. Constructor represents a constructor.
  7. Modifier helps inspect access and other modifiers.
  8. getDeclaredFields() returns fields declared directly in a class.
  9. getDeclaredMethods() returns methods declared directly in a class.
  10. getDeclaredConstructors() returns constructors declared directly in a class.
  11. Method.invoke() can dynamically invoke a method.
  12. Constructor.newInstance() can dynamically create an object.
  13. Field.get() can read a field value.
  14. Field.set() can modify a field when access is permitted.
  15. Class.forName() can load a class using its name.
  16. Reflection can inspect runtime annotations when they have appropriate runtime retention.
  17. Reflection can introduce additional runtime errors and complexity.
  18. Reflective access to encapsulated members is subject to Java's access and module rules.
  19. Reflection can have additional runtime overhead compared with direct access.
  20. Reflection is especially useful in frameworks, testing tools, plugins, and other infrastructure software.

Conclusion

The Java Reflection API provides a mechanism for examining and interacting with classes at runtime.

The most important classes are:

Class
Field
Method
Constructor
Modifier

A simple Reflection flow is:

Class<?> clazz = Student.class;
 
Field[] fields = clazz.getDeclaredFields();
 
Method[] methods = clazz.getDeclaredMethods();
 
Constructor<?>[] constructors =
        clazz.getDeclaredConstructors();

Reflection can also dynamically perform operations:

field.get(object);
field.set(object, value);
 
method.invoke(object, arguments);
 
constructor.newInstance(arguments);

Reflection is a powerful feature of Java and forms an important part of many frameworks and infrastructure libraries. However, it should be used carefully because it can reduce compile-time safety, increase complexity, introduce runtime errors, and interact with Java's access-control and module system.

When a class, method, or field is already known, normal Java code is generally clearer. Reflection becomes especially useful when the program needs to discover or work with types dynamically at runtime.

See you in next page....🙂

← OverviewAnnotations →
← OverviewAnnotations →