google-site-verification: google61fe8ba583a51912.html
Java Reflection API

The Reflection API allows you to inspect and manipulate classes, interfaces, fields, methods, and constructors at runtime. It's a powerful feature that enables dynamic code analysis and execution.

1. Basic Reflection Operations

Getting Class Objects

import java.lang.reflect.*; public class BasicReflection { public static void main(String[] args) throws Exception { // Different ways to get Class object Class<String> stringClass1 = String.class; Class<?> stringClass2 = Class.forName("java.lang.String"); Class<?> stringClass3 = "hello".getClass(); System.out.println("Class name: " + stringClass1.getName()); System.out.println("Simple name: " + stringClass1.getSimpleName()); System.out.println("Canonical name: " + stringClass1.getCanonicalName()); System.out.println("Is interface: " + stringClass1.isInterface()); System.out.println("Modifiers: " + Modifier.toString(stringClass1.getModifiers())); } }

Inspecting Class Structure

import java.lang.reflect.*; import java.util.*; class Person { private String name; private int age; public static int count = 0; 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; } private void privateMethod() { System.out.println("Private method called"); } } public class ClassInspection { public static void main(String[] args) throws Exception { Class<Person> personClass = Person.class; // Inspect fields System.out.println("=== FIELDS ==="); Field[] fields = personClass.getDeclaredFields(); for (Field field : fields) { System.out.println("Field: " + field.getName() + " Type: " + field.getType() + " Modifiers: " + Modifier.toString(field.getModifiers())); } // Inspect methods System.out.println("\n=== METHODS ==="); Method[] methods = personClass.getDeclaredMethods(); for (Method method : methods) { System.out.println("Method: " + method.getName() + " Return: " + method.getReturnType() + " Params: " + Arrays.toString(method.getParameterTypes())); } // Inspect constructors System.out.println("\n=== CONSTRUCTORS ==="); Constructor<?>[] constructors = personClass.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { System.out.println("Constructor: " + constructor.getName() + " Params: " + Arrays.toString(constructor.getParameterTypes())); } } }

2. Working with Fields

Accessing and Modifying Fields

import java.lang.reflect.*; public class FieldManipulation { public static void main(String[] args) throws Exception { Person person = new Person("John", 25); // Access private field Field nameField = Person.class.getDeclaredField("name"); nameField.setAccessible(true); // Bypass access control // Get field value String nameValue = (String) nameField.get(person); System.out.println("Current name: " + nameValue); // Set field value nameField.set(person, "Jane"); System.out.println("New name: " + person.getName()); // Access static field Field countField = Person.class.getDeclaredField("count"); countField.setAccessible(true); System.out.println("Static count: " + countField.get(null)); // Modify static field countField.set(null, 42); System.out.println("Modified static count: " + countField.get(null)); } }

Field Type Information

import java.lang.reflect.*; import java.util.*; public class FieldAnalysis { private String name; private List<Integer> numbers; private Map<String, Object> data; private int[] array; public static void main(String[] args) throws Exception { Class<FieldAnalysis> clazz = FieldAnalysis.class; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println("\nField: " + field.getName()); System.out.println("Type: " + field.getType()); System.out.println("Generic Type: " + field.getGenericType()); // Check if it's a parameterized type if (field.getGenericType() instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) field.getGenericType(); System.out.println("Raw type: " + pType.getRawType()); System.out.println("Type arguments: " + Arrays.toString(pType.getActualTypeArguments())); } // Check if it's an array if (field.getType().isArray()) { System.out.println("Array component type: " + field.getType().getComponentType()); } } } }

3. Working with Methods

Invoking Methods

import java.lang.reflect.*; public class MethodInvocation { public static void main(String[] args) throws Exception { Person person = new Person("Alice", 30); // Get public method and invoke Method getNameMethod = Person.class.getMethod("getName"); String name = (String) getNameMethod.invoke(person); System.out.println("Name via reflection: " + name); // Get method with parameters and invoke Method setAgeMethod = Person.class.getMethod("setAge", int.class); setAgeMethod.invoke(person, 35); System.out.println("New age: " + person.getAge()); // Invoke private method Method privateMethod = Person.class.getDeclaredMethod("privateMethod"); privateMethod.setAccessible(true); privateMethod.invoke(person); // Invoke static method (if existed) // Method staticMethod = Person.class.getMethod("staticMethod"); // staticMethod.invoke(null); // null for static methods } }

Method Parameter Inspection

import java.lang.reflect.*; import java.util.*; class Calculator { public int add(int a, int b) { return a + b; } public double multiply(double x, double y) { return x * y; } private void process(String text, int count, boolean flag) {} } public class MethodAnalysis { public static void main(String[] args) throws Exception { Class<Calculator> clazz = Calculator.class; Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { System.out.println("\nMethod: " + method.getName()); System.out.println("Return type: " + method.getReturnType()); System.out.println("Generic return type: " + method.getGenericReturnType()); // Parameter information Parameter[] parameters = method.getParameters(); Type[] genericParamTypes = method.getGenericParameterTypes(); System.out.println("Parameters:"); for (int i = 0; i < parameters.length; i++) { System.out.println(" " + parameters[i].getName() + " : " + parameters[i].getType() + " (generic: " + genericParamTypes[i] + ")"); } // Exception information Type[] exceptionTypes = method.getGenericExceptionTypes(); if (exceptionTypes.length > 0) { System.out.println("Exceptions: " + Arrays.toString(exceptionTypes)); } } } }

4. Working with Constructors

Creating Instances

import java.lang.reflect.*; public class ConstructorExample { static class Product { private String name; private double price; public Product() { this.name = "Unknown"; this.price = 0.0; } public Product(String name) { this.name = name; this.price = 0.0; } private Product(String name, double price) { this.name = name; this.price = price; } @Override public String toString() { return "Product{name='" + name + "', price=" + price + "}"; } } public static void main(String[] args) throws Exception { // Get default constructor and create instance Constructor<Product> defaultConstructor = Product.class.getConstructor(); Product product1 = defaultConstructor.newInstance(); System.out.println("Default: " + product1); // Get constructor with parameters Constructor<Product> nameConstructor = Product.class.getConstructor(String.class); Product product2 = nameConstructor.newInstance("Laptop"); System.out.println("Name only: " + product2); // Get private constructor Constructor<Product> privateConstructor = Product.class.getDeclaredConstructor(String.class, double.class); privateConstructor.setAccessible(true); Product product3 = privateConstructor.newInstance("Phone", 699.99); System.out.println("Private constructor: " + product3); // Get all constructors System.out.println("\nAll constructors:"); Constructor<?>[] constructors = Product.class.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { System.out.println(constructor + " - accessible: " + constructor.isAccessible()); } } }

5. Advanced Reflection Features

Dynamic Proxy

import java.lang.reflect.*; import java.util.*; interface Service { void serve(); String process(String input); } class RealService implements Service { public void serve() { System.out.println("RealService: serving"); } public String process(String input) { return "Processed: " + input; } } public class DynamicProxyExample { public static void main(String[] args) { RealService realService = new RealService(); // Create dynamic proxy Service proxy = (Service) Proxy.newProxyInstance( Service.class.getClassLoader(), new Class<?>[] { Service.class }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method: " + method.getName()); if (args != null) { System.out.println("Arguments: " + Arrays.toString(args)); } // Call real method Object result = method.invoke(realService, args); System.out.println("After method: " + method.getName()); System.out.println("Result: " + result); return result; } } ); // Use proxy proxy.serve(); proxy.process("test input"); } }

Annotation Processing

import java.lang.annotation.*; import java.lang.reflect.*; // Custom annotations @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @interface MyAnnotation { String value() default ""; int version() default 1; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface Inject { String dependency(); } // Annotated class @MyAnnotation(value = "ClassAnnotation", version = 2) class AnnotatedClass { @MyAnnotation("FieldAnnotation") @Inject(dependency = "userService") private String data; @MyAnnotation("MethodAnnotation") public void annotatedMethod() {} } public class AnnotationProcessing { public static void main(String[] args) throws Exception { Class<AnnotatedClass> clazz = AnnotatedClass.class; // Class annotations MyAnnotation classAnnotation = clazz.getAnnotation(MyAnnotation.class); if (classAnnotation != null) { System.out.println("Class annotation: " + classAnnotation.value() + " version: " + classAnnotation.version()); } // Field annotations Field field = clazz.getDeclaredField("data"); MyAnnotation fieldAnnotation = field.getAnnotation(MyAnnotation.class); Inject injectAnnotation = field.getAnnotation(Inject.class); if (fieldAnnotation != null) { System.out.println("Field annotation: " + fieldAnnotation.value()); } if (injectAnnotation != null) { System.out.println("Inject dependency: " + injectAnnotation.dependency()); } // Method annotations Method method = clazz.getMethod("annotatedMethod"); MyAnnotation methodAnnotation = method.getAnnotation(MyAnnotation.class); if (methodAnnotation != null) { System.out.println("Method annotation: " + methodAnnotation.value()); } // Get all annotations System.out.println("\nAll class annotations:"); Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation.annotationType().getName()); } } }

6. Real-World Examples

Dependency Injection Framework

import java.lang.reflect.*; import java.util.*; class SimpleDIContainer { private Map<Class<?>, Object> instances = new HashMap<>(); private Map<Class<?>, Class<?>> implementations = new HashMap<>(); public <T> void register(Class<T> interfaceType, Class<? extends T> implementation) { implementations.put(interfaceType, implementation); } @SuppressWarnings("unchecked") public <T> T resolve(Class<T> type) throws Exception { if (instances.containsKey(type)) { return (T) instances.get(type); } Class<?> implementation = implementations.getOrDefault(type, type); Constructor<?> constructor = implementation.getDeclaredConstructors()[0]; // Resolve constructor parameters Class<?>[] paramTypes = constructor.getParameterTypes(); Object[] params = new Object[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { params[i] = resolve(paramTypes[i]); } T instance = (T) constructor.newInstance(params); instances.put(type, instance); return instance; } } // Example usage interface UserService { void createUser(String name); } interface EmailService { void sendEmail(String to, String message); } class UserServiceImpl implements UserService { private EmailService emailService; public UserServiceImpl(EmailService emailService) { this.emailService = emailService; } public void createUser(String name) { System.out.println("Creating user: " + name); emailService.sendEmail(name + "@example.com", "Welcome!"); } } class EmailServiceImpl implements EmailService { public void sendEmail(String to, String message) { System.out.println("Sending email to " + to + ": " + message); } } public class DIExample { public static void main(String[] args) throws Exception { SimpleDIContainer container = new SimpleDIContainer(); container.register(UserService.class, UserServiceImpl.class); container.register(EmailService.class, EmailServiceImpl.class); UserService userService = container.resolve(UserService.class); userService.createUser("John Doe"); } }

Object-to-JSON Serializer

import java.lang.reflect.*; import java.util.*; public class JsonSerializer { public static String toJson(Object obj) throws Exception { if (obj == null) return "null"; Class<?> clazz = obj.getClass(); if (clazz.isPrimitive() || isWrapperType(clazz)) { return String.valueOf(obj); } else if (clazz.equals(String.class)) { return "\"" + escapeString(obj.toString()) + "\""; } else if (clazz.isArray()) { return arrayToJson(obj); } else if (Collection.class.isAssignableFrom(clazz)) { return collectionToJson((Collection<?>) obj); } else if (Map.class.isAssignableFrom(clazz)) { return mapToJson((Map<?, ?>) obj); } else { return objectToJson(obj); } } private static String objectToJson(Object obj) throws Exception { Class<?> clazz = obj.getClass(); StringBuilder json = new StringBuilder("{"); Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; field.setAccessible(true); String fieldName = field.getName(); Object value = field.get(obj); json.append("\"").append(fieldName).append("\": ").append(toJson(value)); if (i < fields.length - 1) { json.append(", "); } } json.append("}"); return json.toString(); } private static String arrayToJson(Object array) throws Exception { int length = Array.getLength(array); StringBuilder json = new StringBuilder("["); for (int i = 0; i < length; i++) { Object element = Array.get(array, i); json.append(toJson(element)); if (i < length - 1) { json.append(", "); } } json.append("]"); return json.toString(); } private static String collectionToJson(Collection<?> collection) throws Exception { StringBuilder json = new StringBuilder("["); Iterator<?> iterator = collection.iterator(); while (iterator.hasNext()) { Object element = iterator.next(); json.append(toJson(element)); if (iterator.hasNext()) { json.append(", "); } } json.append("]"); return json.toString(); } private static String mapToJson(Map<?, ?> map) throws Exception { StringBuilder json = new StringBuilder("{"); Iterator<?> iterator = map.keySet().iterator(); while (iterator.hasNext()) { Object key = iterator.next(); Object value = map.get(key); json.append("\"").append(key).append("\": ").append(toJson(value)); if (iterator.hasNext()) { json.append(", "); } } json.append("}"); return json.toString(); } private static boolean isWrapperType(Class<?> clazz) { return clazz.equals(Integer.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Boolean.class) || clazz.equals(Short.class) || clazz.equals(Byte.class) || clazz.equals(Character.class); } private static String escapeString(String str) { return str.replace("\"", "\\\"") .replace("\\", "\\\\") .replace("/", "\\/") .replace("\b", "\\b") .replace("\f", "\\f") .replace("\n", "\\n") .replace("\r", "\\r") .replace("\t", "\\t"); } } // Test the serializer class TestObject { private String name = "John"; private int age = 30; private boolean active = true; private String[] tags = {"java", "reflection"}; private List<Integer> scores = Arrays.asList(95, 87, 92); // getters and setters... } public class SerializerExample { public static void main(String[] args) throws Exception { TestObject obj = new TestObject(); String json = JsonSerializer.toJson(obj); System.out.println(json); } }

7. Performance Considerations and Best Practices

import java.lang.reflect.*; import java.util.concurrent.*; public class ReflectionPerformance { private static final int ITERATIONS = 1000000; // Regular method call public static int directCall(Person person) { return person.getAge(); } // Reflection method call public static int reflectionCall(Person person) throws Exception { Method method = Person.class.getMethod("getAge"); return (int) method.invoke(person); } // Cached reflection call private static final Method CACHED_METHOD; static { try { CACHED_METHOD = Person.class.getMethod("getAge"); } catch (Exception e) { throw new RuntimeException(e); } } public static int cachedReflectionCall(Person person) throws Exception { return (int) CACHED_METHOD.invoke(person); } public static void main(String[] args) throws Exception { Person person = new Person("Test", 25); // Warm up for (int i = 0; i < 1000; i++) { directCall(person); reflectionCall(person); cachedReflectionCall(person); } // Benchmark direct calls long start = System.nanoTime(); for (int i = 0; i < ITERATIONS; i++) { directCall(person); } long directTime = System.nanoTime() - start; // Benchmark reflection calls start = System.nanoTime(); for (int i = 0; i < ITERATIONS; i++) { reflectionCall(person); } long reflectionTime = System.nanoTime() - start; // Benchmark cached reflection calls start = System.nanoTime(); for (int i = 0; i < ITERATIONS; i++) { cachedReflectionCall(person); } long cachedReflectionTime = System.nanoTime() - start; System.out.println("Direct calls: " + directTime / 1000000 + " ms"); System.out.println("Reflection calls: " + reflectionTime / 1000000 + " ms"); System.out.println("Cached reflection calls: " + cachedReflectionTime / 1000000 + " ms"); } }

Key Points and Best Practices

  1. Performance: Reflection is slower than direct calls - cache Method/Field/Constructor objects when possible
  2. Security: Use setAccessible(true) carefully as it bypasses access controls
  3. Exception Handling: Reflection methods throw checked exceptions that must be handled
  4. Type Safety: Loss of compile-time type safety - use generics and casting carefully
  5. Use Cases: Frameworks, ORM tools, dependency injection, testing tools
  6. Alternatives: Consider Method Handles (Java 7+) for better performance

Reflection is powerful but should be used judiciously due to performance overhead and reduced type safety.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper