Given an generic interface like
interface DomainObjectDAO<T>
{
T newInstance();
add(T t);
remove(T t);
T findById(int id);
// etc...
}
I'd like to create a subinterface that specifies the type parameter:
interface CustomerDAO extends DomainObjectDAO<Customer>
{
// customer-specific queries - incidental.
}
The implementation needs to know the actual template parameter type, but of course type erasure means isn't available at runtime. Is there some annotation that I could include to declare the interface type? Something like
@GenericParameter(Customer.class)
interface CustomerDAO extends DomainObjectDAO<Customer>
{
}
The implementation could then fetch this annotation from the interface and use it as a substitute for runtime generic type access.
Some background:
This interface is implemented using JDK dynamic proxies as outlined here. The non-generic version of this interface has been working well, but it would be nicer to use generics and not have to create the methods in a subinterface just to specify the domain object type. Generics and proxies take care of most things, but the actual type is needed at runtime to implement the newInstance
method, amongst others.
To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class. As you can see, all occurrences of Object are replaced by T.
Definition: “A generic type is a generic class or interface that is parameterized over types.” Essentially, generic types allow you to write a general, generic class (or method) that works with different types, allowing for code re-use.
The question mark ( ? ) wildcard character can be used to represent an unknown type using generic code. Wildcards can be used with parameters, fields, local variables, and return types.
It is possible to find the actual type argument of the Dao sub-interface (CustomerDAO), by invoking the following method:
import java.lang.reflect.ParameterizedType;
public static Class<?> getDomainClass(final Class<?> daoInterface) {
ParameterizedType type = (ParameterizedType) daoInterface.getGenericInterfaces()[0];
return (Class<?>) type.getActualTypeArguments()[0];
}
When you call it like
Class<?> domainClass = getDomainClass(daoInterface);
with daoInterface == CustomerDAO.class
, then you will get domainClass == Customer.class
.
In my implementation, a DaoFactory
performs this call and uses the domainClass
as a constructor argument for the DaoInvocationHandler
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With