views:

70

answers:

3

I couldn't find a duplicate for this question for Java, although there are a lot of them for C#.

I have this method:

public <T> T getSomething() {
 //
}

According to the type of T, I will have a different return. For example:

String a = getSomething();
int b = getSomething();

For a, my method will return a specific String. For b, it will return a specific int. And so on.

It seems that this can be done with typeof() in C#. How can I achieve it in Java?

+1  A: 

Unfortunately this is not possible with Java because it uses a technique called "type erasure" to allow generics to work without changing the JVM. The upshot is that when the method is called, all it knows about are Objects, so it can't ever find out what type it is expected to return.

Gabe
The JVM was changed to support generics. The point of erasure is that it allows relatively seamless operation with pre-1.5 code. It also removes some overhead.
Tom Hawtin - tackline
I couldn't find much of a reference to how the JVM was changed, other than to support the modified classfile format to contain the additional metadata. How does it remove overhead? As I understand it, erased types mean implicit casting, which adds overhead.
Gabe
A: 

Your example doesn't work unless you have some code inside the getSomething method. If I write

public <T> T getSomething(){ return null;}

it compiles, but it's meaningless. However, you'd normally get your T from the context:

public class Foo<T>{ 
  public T getSomething()... 
}
new Foo<String>().getSomething()...

Presumably there'd have to be something in your implementation that's type aware.

Steve B.
A: 

In Java, it would be more normal to write something like:

public <T> List<T> getSomeThings() {
    //
}

That works just fine.

Possibly the direct equivalent of what you have seen in C# would go something like:

public <T> T getSomething(Class<? extends T> clazz) {
    //
}

But will use reflection, which will almost certainly be a bad idea. You can, of course, avoid reflection using a bog standard factory:

public <T> T getSomething(FactoryThing<? extends T> factory) {
    //
}

There are occasional cases where inferring the return type is useful. For instance, reading from a Java serialisation stream where due to pre-1.5 API design, unchecked cast warnings are not reasonably avoidable. I suggest keeping this tight with a package-private method.

Tom Hawtin - tackline