Java Reflection for Classes

Java Reflection is a powerful API that allows us to inspect and manipulate classes, methods, fields, and other components at runtime. Using reflection, we can obtain information about classes and their members, create instances, and invoke methods dynamically.

Introduction to Java Reflection for Classes

The java.lang.Class class is the entry point for all reflection operations. Every Java object belongs to a class, and the Class class provides methods to obtain metadata about the class, its methods, fields, constructors, and more.

Obtaining Class Object

To use reflection, we first need to obtain a Class object representing the class we want to inspect. There are several ways to obtain a Class object:

  1. Using .class syntax:

    Class<?> clazz = MyClass.class;
    
  2. Using getClass() method on an instance:

    MyClass obj = new MyClass();
    Class<?> clazz = obj.getClass();
    
  3. Using Class.forName() method:

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

Inspecting Class Information

Once we have a Class object, we can use its methods to obtain various information about the class.

Example: Inspecting Class Information

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionClassExample {
    public static void main(String[] args) {
        try {
            // Obtain the Class object
            Class<?> clazz = Class.forName("java.util.ArrayList");

            // Get the class name
            System.out.println("Class Name: " + clazz.getName());

            // Get the package name
            System.out.println("Package Name: " + clazz.getPackage().getName());

            // Get the superclass
            System.out.println("Superclass: " + clazz.getSuperclass().getName());

            // Get the implemented interfaces
            Class<?>[] interfaces = clazz.getInterfaces();
            System.out.println("Implemented Interfaces:");
            for (Class<?> iface : interfaces) {
                System.out.println(" - " + iface.getName());
            }

            // Get the constructors
            Constructor<?>[] constructors = clazz.getConstructors();
            System.out.println("Constructors:");
            for (Constructor<?> constructor : constructors) {
                System.out.println(" - " + constructor);
            }

            // Get the methods
            Method[] methods = clazz.getDeclaredMethods();
            System.out.println("Methods:");
            for (Method method : methods) {
                System.out.println(" - " + method);
            }

            // Get the fields
            Field[] fields = clazz.getDeclaredFields();
            System.out.println("Fields:");
            for (Field field : fields) {
                System.out.println(" - " + field);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Output:

Class Name: java.util.ArrayList
Package Name: java.util
Superclass: java.util.AbstractList
Implemented Interfaces:
 - java.util.List
 - java.util.RandomAccess
 - java.lang.Cloneable
 - java.io.Serializable
Constructors:
 - public java.util.ArrayList(int)
 - public java.util.ArrayList()
 - public java.util.ArrayList(java.util.Collection<? extends E>)
Methods:
 - public boolean java.util.ArrayList.add(java.lang.Object)
 - public void java.util.ArrayList.add(int,java.lang.Object)
 - public boolean java.util.ArrayList.addAll(java.util.Collection<? extends E>)
 - public boolean java.util.ArrayList.addAll(int,java.util.Collection<? extends E>)
 - public void java.util.ArrayList.ensureCapacity(int)
 - public void java.util.ArrayList.forEach(java.util.function.Consumer<? super E>)
 - public E java.util.ArrayList.get(int)
 - public boolean java.util.ArrayList.remove(java.lang.Object)
 - public E java.util.ArrayList.remove(int)
 - public boolean java.util.ArrayList.removeAll(java.util.Collection<?>)
 - public boolean java.util.ArrayList.retainAll(java.util.Collection<?>)
 - public E java.util.ArrayList.set(int,E)
 - public int java.util.ArrayList.size()
 - public java.util.Spliterator<E> java.util.ArrayList.spliterator()
 - public java.util.stream.Stream<E> java.util.ArrayList.stream()
 - public java.lang.String java.util.ArrayList.toString()
 - public void java.util.ArrayList.trimToSize()
Fields:
 - private static final long java.util.ArrayList.serialVersionUID
 - private static final int java.util.ArrayList.DEFAULT_CAPACITY
 - private static final java.lang.Object[] java.util.ArrayList.EMPTY_ELEMENTDATA
 - private static final java.lang.Object[] java.util.ArrayList.DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 - transient java.lang.Object[] java.util.ArrayList.elementData
 - private int java.util.ArrayList.size

Using Reflection with Custom Classes

We can also use reflection to inspect and manipulate custom classes.

Example: Inspecting a Custom Class

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Person {
    private String name;
    private int age;

    public Person() {}

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class CustomClassReflectionExample {
    public static void main(String[] args) {
        try {
            // Obtain the Class object for the custom class
            Class<?> clazz = Class.forName("Person");

            // Get the class name
            System.out.println("Class Name: " + clazz.getName());

            // Get the package name
            System.out.println("Package Name: " + clazz.getPackage().getName());

            // Get the superclass
            System.out.println("Superclass: " + clazz.getSuperclass().getName());

            // Get the constructors
            Constructor<?>[] constructors = clazz.getConstructors();
            System.out.println("Constructors:");
            for (Constructor<?> constructor : constructors) {
                System.out.println(" - " + constructor);
            }

            // Get the methods
            Method[] methods = clazz.getDeclaredMethods();
            System.out.println("Methods:");
            for (Method method : methods) {
                System.out.println(" - " + method);
            }

            // Get the fields
            Field[] fields = clazz.getDeclaredFields();
            System.out.println("Fields:");
            for (Field field : fields) {
                System.out.println(" - " + field);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Output:

Class Name: Person
Package Name: (default package)
Superclass: java.lang.Object
Constructors:
 - public Person()
 - public Person(java.lang.String,int)
Methods:
 - public java.lang.String Person.getName()
 - public void Person.setName(java.lang.String)
 - public int Person.getAge()
 - public void Person.setAge(int)
 - public java.lang.String Person.toString()
Fields:
 - private java.lang.String Person.name
 - private int Person.age

Conclusion

Java Reflection is used that allows us to inspect and manipulate classes and their members dynamically. By understanding how to use reflection for classes, you can enhance the flexibility and introspection capabilities of your Java applications. For more detailed information on Java Reflection, you can refer to the official Java Reflection API documentation.

Comments