0

In a generic method, I don't seem to be able to access the generic type of the method at runtime (error: cannot select from a type variable).

public <A> A get(Animal a) {
    Class ac = a.getClass();
    if(ac.isAssignableFrom(A.class)) {  // <- not working!
        return (A) a;
    } else {
        // error handling
    }
}

The reason why I do this is to be able to safely downcast stuff, like:

Animal a = new Dog();
Dog d = get(a);    // <- OK
Cat c = get(a)     // <- incompatible types, caught by else block

I've found a post from over 9 years ago with the exact same problem: https://forums.oracle.com/forums/thread.jspa?threadID=1184291

There, the idea to solve this was to provide a Class object in the constructor and use this variable to check if it's assignable. Which seems a pretty stupid solution, as you could just put any class in there and all the nice typechecking was useless...

So, same question: Why should one supply <any>.class in the constructor, when during runtime the type of <A> is perfectly known? How can I access the actual type of <A>?


Found a pretty ugly solution:

public <A> A get(Animal a, Class<A> clazz) {
    // same as above...
}

So now you have to provide a Class, but the only valid class you can insert here is your return type. But at least now it's typesafe.

Just totally inconvenient...

klamann
  • 1,697
  • 17
  • 28

2 Answers2

4

Contrary to your assertion, the type of A is not known during runtime. Take a look at the docs concerning type erasure for more details.

Briefly, the runtime knows you have an object of type Whatever. However it can't distinguish between Whatever<A> and Whatever<B> without you explicitly providing the info. That's why it's suggested that you provide a class object. Note this is distinct from the compilation phase, in which the complete type info is known.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
1

It is not possible to select the generic type at runtime.

See here for a possible solution: Access generic type parameter at runtime?

Community
  • 1
  • 1
Felix
  • 533
  • 4
  • 11