The ReflectoType class is a cornerstone of the Cariochi Reflecto library, offering a rich and intuitive interface for comprehensive type introspection and manipulation in Java. It simplifies accessing detailed information about any given type, making reflective programming more accessible and powerful.
Complete Type Information
ReflectoType provides a unified approach to access a wealth of information about types:
Actual Type and Arguments: Discern the actual type, including generic type arguments, enabling precise type manipulation and inspection.
Fields and Methods: Access detailed information about fields and methods, including their types, visibility, and whether they are static or instance members. Choose between declared members or all members, with support for including or excluding enclosing class members.
Modifiers: Examine a type's modifiers, such as visibility (public, private), abstraction (abstract classes, interfaces), and more.
Constructors: List a type's constructors, facilitating dynamic object instantiation.
Super Type and Interfaces: Identify a type's superclass and implemented interfaces, preserving generic type information.
Special Types: Special handling for arrays and enums, including component type access and enum constant retrieval.
Utility Methods: Includes methods like is(), as(), isAssignableFrom(), and isInstance() to query type properties and relationships intuitively.
Example Usage
Here are some practical examples demonstrating the power of ReflectoType:
Constructors
ReflectoType type =reflect(Types.type(ArrayList.class,String.class));List<ReflectoConstructor> constructors =type.constructors().list();List<ReflectoConstructor> declaredConstructors =type.declared().constructors().list();// find constructor by parameter typesReflectoConstructor constructor =type.constructors().find(Collection.class).orElseThrow();Object instance =constructor.newInstance(Set.of(1));
Methods
// lists methodsList<ReflectoMethod> methods =type.methods().list();List<ReflectoMethod> declaredMethods =type.declared().methods().list();List<ReflectoMethod> includeEnclosingMethods =type.includeEnclosing().methods().list();// find and invoke methodReflectoMethod method =type.methods().find("setUsername(?)",String.class).orElseThrow();TargetMethod targetMethod =method.withTarget(user);targetMethod.invoke("test_user");// filter methodsList<ReflectoMethods> postProcessors =type.declared().methods().stream().filter(method ->method.modifiers().isPublic()).filter(method ->method.annotations().contains(PostProcessor.class)).filter(method ->method.returnType().is(void.class)).filter(method ->method.parameters().size() ==1).collect(Collectors.toList());// find and invoke a static methodReflectoMethod method =type.methods().find("sayHello(?)",String.class).orElseThrow();TargetMethod staticMethod =method.asStatic();String result =staticMethod.invoke("World");
Fields
// list fieldsList<ReflectoField> fields =type.fields().list();List<ReflectoField> declaredFields =type.declared().fields().list();List<ReflectoField> includeEnclosingFields =type.includeEnclosing().fields().list();// find fieldReflectoField field =type.fields().find("username").orElseThrow();TargetField targetField =field.withTarget(user);String username =targetField.getValue();targetField.setValue("test_user");// filter fieldsList<ReflectoField> fields =type.declared().fields().stream().filter(field ->field.modifiers().isPrivate()).filter(field ->field.annotations().contains(NotNull.class)).filter(field ->field.type().is(String.class)).collect(toList());// find static fieldReflectoField field =type.fields().find("NAME",String.class).orElseThrow();TargetField staticField =field.asStatic();String name =staticField.getValue();staticField.setValue("New Name");
ReflectoType type =Reflecto.reflect(Types.listOf(String.class));assertThat(type.is(Iterable.class)).isTrue();assertThat(type.is(Types.type(Iterable.class,String.class))).isTrue();assertThat(type.is(Types.type(Iterable.class,Long.class))).isFalse();assertThat(type.as(Iterable.class).arguments().get(0).actualType()).isEqualTo(String.class);assertThat(type.isAssignableFrom(ArrayList.class)).isTrue();assertThat(type.isAssignableFrom(Types.type(ArrayList.class,String.class))).isTrue();assertThat(type.isAssignableFrom(Types.type(ArrayList.class,Long.class))).isFalse();assertThat(type.isInstance(newArrayList<>())).isTrue();
Inspecting Types
This example demonstrates how to use the Reflecto library to introspect generic types in Java, using a Dto<T> class as the case study.
// Example Dto class with genericspublicstaticclassDto<T> {privateT value;privateDto<T> child;privateSet<Dto<T>> set;privateMap<String,Set<Dto<T>>> map;}Type type =Types.type(Dto.class,Integer.class);ReflectoType reflectoType =Reflecto.reflect(type);// Type of the first argumentassertThat(reflectoType.arguments().get(0).actualType()).isEqualTo(Integer.class);assertThat(reflectoType.reflect("[0]").actualType()).isEqualTo(Integer.class);// Type of the 'value' fieldassertThat(reflectoType.reflect("value").actualType()).isEqualTo(Integer.class);// Type of the 'child.value' nested fieldassertThat(reflectoType.reflect("child.value").actualType()).isEqualTo(Integer.class);// Type of the first argument (T) of the first argument (Dto<T>) of the 'set' field type (Set<Dto<T>>)assertThat(reflectoType.reflect("set[0][0]").actualType()).isEqualTo(Integer.class);// Type of the 'value' field (T) of the first argument (Dto<T>) of the 'set' field type (Set<Dto<T>>)assertThat(reflectoType.reflect("set[0].value").actualType()).isEqualTo(Integer.class);// Type of the first argument (String) of the nested 'child.map' field type (Map<String, Set<Dto<T>>>)assertThat(reflectoType.reflect("child.map[0]").actualType()).isEqualTo(String.class);// Type of the 'value' field (T) of the first argument (Dto<T>) of the second argument (Set<Dto<T>>) of the 'child.map' nested field type (Map<String, Set<Dto<T>>>)
assertThat(reflectoType.reflect("child.map[1][0].value").actualType()).isEqualTo(Integer.class);
Conclusion
The ReflectoType class from Cariochi Reflecto offers a comprehensive toolkit for working with Java types reflectively. It simplifies obtaining detailed information about types, their relationships, and their members, enabling developers to write more dynamic, type-safe, and intuitive reflective code. Whether dealing with complex generic types, navigating type hierarchies, or performing runtime type checks and conversions, ReflectoType provides all the necessary functionalities in an accessible manner.