I am using reflection proxies to perform additional checking on a public API. Essentially I want to wrap every object that comes back from it so that any object the caller gets their hands on is a proxy to the real object.
Java still has the whole erasure problem, so I am passing the type of the wrapped object around with it. I should know what type everything is because the entry into the API is a single, non-generic interface.
public class ProxyInvocationHandler implements InvocationHandler {
private final Object delegate;
private final Type delegateType;
public ProxyInvocationHandler(Object delegate, Type delegateType) {
this.delegate = delegate;
this.delegateType = delegateType;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
// Omitted: additional checks performed here.
Object result = method.invoke(delegate, args);
Type returnType = method.getGenericReturnType();
// e.g. if delegateType is List<Cat> and the method is the get method,
// returnType would be E but resultType should be Cat.
Type resultType = ???
// Utility method I will omit, it just creates another proxy instance
// using its own invocation handler.
return ProxyUtils.wrap(result, resultType);
}
}
I have looked around the Type / ParametrizedType API and can’t seem to find a way to get resultType, even though delegateType and returnType should be enough information to compute this.
What is the “proper” way to do this?
You can use Java ClassMate for that purpose. You’ll have to use
com.fasterxml.classmate.GenericTypefor type tokens:Note the empty
{}that’s called the “Super-type Token” pattern.Cache the results in a
Map:Now, when you have a method declared by the
delegateType, i.e.List, you can get its resolved return type: