Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generic function: how to return Generic type

Tags:

java

generics

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.

like image 642
bmargulies Avatar asked Dec 24 '09 16:12

bmargulies


People also ask

How do I return a generic response in Java?

(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.

How do you find a generic type?

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.

How do you declare a generic method How do you invoke a generic 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.


1 Answers

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.

like image 68
BalusC Avatar answered Oct 26 '22 20:10

BalusC