Table of contents
- source code;
- client type dispatching interface;
- type dispatcher implementation;
- type dispatcher unit test;
- type arguments resolver contract;
- type arguments resolver implementation
- type arguments resolver unit test
All source code packaged as a Maven project may be downloaded here
I wrote about utility class for generic type arguments processing earlier. However, it became obvious that its contract may be extended and implementation can be greatly improved as I started to use the class. General considerations:
- define generic interface that works in terms of Type (Class was used earlier). E.g. it shoud be legal to provide Comparable as an object of ParameterizedType class as a 'base' type and get ParameterizedType from processing method back;
- avoid type casts as much as possible;
Let's start from the second concern. Standard java reflection api defines generics-related interfaces hierarchy with root java.lang.reflect.Type (ParameterizedType, TypeVariable etc). However, the api doesn't provide convenient way to work with it. I mean the following situation - suppose you have a reference variable which static type is 'Type'. There is no way to check if it, say, 'ParameterizedType' over than direct examination ('instanceof', Class.isAssignableFrom() etc).
Conclusion - we need to perform such manual checks but they should be localized as much as possible in order to have most of the code work without them. Also that functionality should be flexible enough to be reusable at another generics-related tasks.
I solved it via classic GoF Visitor pattern. Here is a base interface to be used at the client side:
Convenient adapter implementation:
And eventually type dispatcher, the only place that encapsulates all explicit type casts:
Simple mock unit test for the dispatcher at jmock2 format:
Finally, here is an interface that defines basic contract for type arguments resolving:
Type arguments resolver implementation:
And finally unit test for the type arguments resolver implementation:
You can take a brief look at the unit-test in order to check that even complex situations with big class hierarchies and replaced type parameters are correctly resolved.