I'm driving crazy with the bounded class...
I defined such a method :
protected <X> DataAccessResult<List<X>> executeQuery(final String query, final Class<X> elementType,Object... args)
And I want to call it with the following arguments:
Query : a SQL query, what it actually does doesn't matter
elementType : I need something like Map<String,Object>.class
, because what I need to get is a DataAccessResult<List<Map<String,Object>>>
But Map<String,Object>.class
doesn't compile, and Map.class
doesn't allow me to have a DataAccessResult<List<Map<String,Object>>>
as result type.
I mean :
DataAccessResult<List<Map>> x = executeQuery("Select * from table",Map.class, (Object[]) null);
DataAccessResult<Map<String,Object>>> y = (DataAccessResult<Map<String,Object>>>) x;
provoke a cast error
and DataAccessResult<List<Map<String,Object>>> x = executeQuery("Select * from table",Map.class, (Object[]) null);
doesn't work either..
What could be the correct syntax?
Thanks!
Short answer: you can not really do it. At least not in normal Java syntax. There are workarounds however.
The first is, you just explicitly specify X
on the caller side this way:
protected <X> DataAccessResult<List<X>> executeQuery(final String query, Object... args)
this.<Map<String, Object>>executeQuery("Select * from table");
You could also pass in an object instead of a class, that can "carry" the generic parameters:
protected <X> DataAccessResult<List<X>> executeQuery(final String query, X prototype, Object... args)
executeQuery("Select * from table", new Map<String, Object>());
Both of these require no additional work, but are admittedly clumsy. The third option is to introduce a replacement for the Class<T>
construct, which can carry generic parameters. This would word like this:
protected <X> DataAccessResult<List<X>> executeQuery(final String query, JavaType<X> type, Object... args)
executeQuery("Select * from table", map(String.class, Object.class));
Where JavaType could look like this:
public class JavaType<T> {
public static <K, V> JavaType<Map<K, V>> map(Class<K> keyType, Class<V> valueType) {
new JavaType<Map<K, V>>();
}
}
This JavaType<T>
class can be then extended with normal classes, lists, whatever you need. It could even carry the necessary class objects if you need them for reflection.