Here's a Java generic pattern:
public <T> T getResultData(Class<T> resultClass, other_args) {
...
return resultClass.cast(T-thing);
}
A typical call looks like:
DoubleBuffer buffer;
buffer = thing.getResultData(DoubleBuffer.class, args);
I've never been able to figure out how to use this pattern cleanly when the desired return type is, itself, generic. To be 'concrete', what if a function like this wants to return Map<String,String>
? Since you can't get a class object for a generic, of course, the only option would be to pass Map.class
, and then you need a cast and an @SuppressWarning
after all.
One ends up with a call like:
Map<String, String> returnedMap;
returnedMap = thing.getResultData(Map.class, some_other_args);
Now one is back to needing casts and suppressing a warning.
I suppose that one could take something from the java.lang.reflect.Type
family instead of the Class
, but those aren't especially easy to concoct. That looks like:
class Dummy {
Map<String, String> field;
}
...
Type typeObject = Dummy.class.getField("field").getGenericType();
Given this, the called function could extract the base type and use that for casting or newInstance-ing, but the dummy field business sure looks ugly.
Note that functions like this are not always calling newInstance
. Obviously, if they do, they don't need to call resultClass.cast
.
(Yes, this is legal code; see Java Generics: Generic type defined as return type only.) The return type will be inferred from the caller. However, note the @SuppressWarnings annotation: that tells you that this code isn't typesafe. You have to verify it yourself, or you could get ClassCastExceptions at runtime.
Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.
Generic MethodsAll generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the method's return type ( < E > in the next example). Each type parameter section contains one or more type parameters separated by commas.
You cannot do that in the standard Java API. However, there are utility classes available which can get the Type
out of a generic class. In for example Google Gson (which converts JSON to fullworthy Javabeans and vice versa) there's a TypeToken
class. You can use it as follows:
List<Person> persons = new Gson().fromJson(json, new TypeToken<List<Person>>() {}.getType());
Such a construct is exactly what you need. You can find here the source sode, you may find it useful as well. It only requires an additional getResultData()
method which can accept a Type
.
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