Generics and Runtime Type Information

Runtime Type Information (RTTI) is a mechanism that allows Java programs to discover and use type information at runtime, rather than at compile time.

This capability is essential for features such as:

  • Dynamic type checking
  • Reflection
  • Polymorphism
  • Generic type handling (with limitations due to type erasure)

Why RTTI ?

At compile time, Java enforces type rules to prevent incorrect type usage. However, during execution, Java still needs to:

  • Know what actual type an object is (for method dispatch)
  • Handle cases like instanceof, casting, and reflection

Program

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

public class GenericsRTTIDemo {
    // Generic method with Class<T> to retain type info
    public static <T> T createInstance(Class<T> clazz) throws Exception {
        return clazz.getDeclaredConstructor().newInstance();
    }

    // Generic method to check and process a list
    public static void processList(List<?> list) {
        System.out.println("List class: " + list.getClass().getSimpleName());
        // Cannot check List<String> at runtime, but can check List
        if (list instanceof List) {
            System.out.println("Contains: " + list);
        }
    }

    // Class to capture generic type at runtime
    static abstract class TypeReference<T> {
        Type getType() {
            return ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
    }

    public static void main(String[] args) throws Exception {
        // Demonstrate type erasure
        List<String> stringList = new ArrayList<>();
        List<Integer> intList = new ArrayList<>();
        System.out.println("Same class at runtime? " + (stringList.getClass() == intList.getClass())); // true

        // Use Class<T> to create instance
        String s = createInstance(String.class);
        System.out.println("Created: " + s.getClass().getSimpleName()); // String

        // Process a generic list
        stringList.add("Hello");
        processList(stringList); // List class: ArrayList, Contains: [Hello]

        // Capture generic type at runtime
        TypeReference<List<String>> ref = new TypeReference<>() {};
        System.out.println("Captured type: " + ref.getType()); // java.util.List<java.lang.String>
    }
}

/*
Same class at runtime? true
Created: String
List class: ArrayList
Contains: [Hello]
Captured type: java.util.List<java.lang.String>
*/
Scroll to Top