Skip to content

Reflection assist

When class is deeply analyzed (often methods or fields processing) context is prepared once and navigated to required type in the hierarchy:

// preparing generics context before analysis because it would be impossible
// to resolve correct generics for required class in hierarchy
GenericsContext context = GenericsResolver.resolve(Root);

analyzeType(context, Root.class);

void analyzeType(GenericsContext context) {
    Class type = context.currentClass();
    // do some analysis (e.g. review methods)
    for(Method method: type.getDeclaredMethods()) {
        Class res = context.method(method).resolveReturnClass();
        // collection returned
        if (Iterable.isAssignableFrom(res)) {
            Class collectionType = context.method(method)
                                        .resolveReturnTypeGeneric();
            //...
        }        
    }

    // example type resolvution inside class (note there is a shortcut method .resolveFieldClass(),
    // here raw resolution used as an example)
    Class fieldType = context.resolveClass(type.getDeclaredField("smth").getGenericType())

    // continue analysis for superclass
    Class superclass = type.getSuperclass();    
    analyzeType(context.type(superclass));
}

Type utils

To avoid dealing with type objects (ParameterizedType) context provides pure utility methods (not actually tied to "context"): - context.resolveTypeGenerics(type) resolved generics of provided type - context.resolveClass(type) returns raw type's class (reducing type information) - context.resolveType(type) return type with replaced variables

public class Base<T> {
    T field;
}
public class Root extends Base<List<String>> {}

GenericsContext context = GenericsResolver.resolve(Root.class).type(Base.class);
// List<String>
Type fieldType = Base.class.getDeclaredField("field");
// type class
context.resolveClass(fieldType) == List.class;
// first generic class (type information may be reduced)
context.resolveGenericOf(fieldType) == String.class;
// general case (no type precision lost)
context.resolveTypeGenerics(fieldType) == [String.class];

Tip

You may use commons-lang ConstructorUtils, FieldUtils or MethodUtils to simplify fields, methods or constructor searches (for example, if you know field name but don't know exact type in hierarchy).