Calling a method with a generic return type in Java

In C ++, you can specify the return type of a function in a parameter, for example:

C ++

float* myFloat = CollectionClass.ptr<float>(); int* myInt = CollectionClass.ptr<int>(); 

Is there an equivalent in Java for specifying a return type without adding additional class arguments?

Java

  //This doesn't work (due to type erasure) public <T> T getDate() { if (T instanceof Date) return new Date(); if (T instanceof Calendar) return new Calendar(); } Date myDate = getDate<Date>(); 
+8
java function generics methods
source share
3 answers

This is great to declare a method with the signature public <T> T getDate() .

However, it is not possible to implement a method that returns what you want. That the method at run time cannot depend only on its type parameter, because it does not know its type parameter.

To get an intuition for this, understand that any code written using generics can also be written equivalently without using generics, simply by deleting the general parameters and inserting the ghosts if necessary. This is what type erasure means.

Therefore, to find out if your method is possible in Generics, just ask how you would do it without Generics:

 public Object getDate() { // what would you do here? } Date myDate = (Date)getDate(); 

If you cannot do this without Generics, you also cannot do this with Generics.

C ++ templates are completely different. For C ++ template functions and classes, templates generate a “separate copy” of a function or class for each type argument that is used with it. that is, the compiler accepts the boilerplate code and “copies and pastes” it into several versions, each separately. Therefore, each copy of the code is specific to a particular type argument and therefore can use this type at run time.

That's why C ++ - boilerplate code must be available in source form so that you can use it - there are no such templates as "compiled" ones. However, in Java, you can use a compiled generic class. Generic classes and methods in Java do not imply anything about the types that they can use.

+16
source share

Ok, now with editing so that it is clear that the code has a value of T ...

No, there is nothing easy in Java to do this job - due to type erasure, as your question mentions. You can go to Class<T> :

 public <T> T getDate(Class<T> clazz) { // Now use clazz to work out what to do } 

... but you cannot do anything that depends on the "value" of T at run time, as that is simply not known. Generics are somewhat anemic in Java, unfortunately :(


EDIT: before editing, make the code conditional on T ...

This is just a question about another type argument:

 import java.util.Date; class Test { public static <T> T getDate() { return (T) new Date(); } public <T> T getDateInstanceMethod() { return (T) new Date(); } public static void main (String [] args) { Date date = Test.<Date>getDate(); // Compiles fine, but is obviously bogus. String string = Test.<String>getDate(); // And specifying a type argument for an instance method Test test = new Test(); date = test.<Date>getDate(); } } 

I always prefer to "put type arguments immediately before regular arguments", but there we go ...

EDIT: As rgettman points out, the input type will do everything for you anyway, so you don't need to specify type arguments in many cases. Sometimes you do it.

+7
source share

With Arrays.asList , it is sometimes necessary to specify the type of the return value. Java tries to narrow the return type based on the common supertype (s) of all arguments, but sometimes you need a specific type. For example,

 List<Number> list = Arrays.asList(1, 2, 3); 

Here Arrays.asList returns a List<Integer> , and you get a compiler error. To return it List<Number> , you must specify a generic type.

 List<Number> list = Arrays.<Number>asList(1, 2, 3); 
+1
source share

All Articles