I have two functions defined as
<T1 extends A> void func1(Class<T1> C);
<T2 extends B> void func2(Class<T2> C);
Now user will give any type at runtime, based on what he gives we need to call either func1 or func2. I need something similar to
<T> void func(Class<T> C){
// check if Class C extends A, then call func1 else call func2
if (T extends A){
func1(C);
}
else{
func2(C);
}
}
I am new to Java Generics and I want to know whether this is possible or not? And if possible how should I do it?
It's not, at least, not with generics.
Generics are almost entirely a figment of the compiler's imagination.
At compile time, generics info is there, but only as much as your eyeballs can see. If I write:
then your eyeballs cannot tell what T is going to be on any given invocation of the
foo
method, looking just at this code. So the compiler can't tell either, and at compile time you therefore don't know what the T is. You can't write code that goes: "Give me whatever T is, perhaps in the form of a java.lang.Class instance".At runtime this information no longer exists - that's called erasure.
There is some generics available at runtime - basically, any time generics appears in a signature (that is, the type of a field, of any type mentioned in an
extends
orimplements
line, any method return type, any method parameter type) - you can still get that at runtime, but all you get is what is literally written in your code.So, once you ask the question: Can I somehow mix runtime concepts such as
jlClassInstance.isAssignableFrom
andinstanceof
with a generics bound, the answer is a simple, flat: No. Not possible. - and yet that's what you are asking.I did mention that, PROVIDED that the method(s) in question have, in their source code, the types explicitly listed, well, now it's part of signatures and you can theoretically query this at runtime. So if you have:
then it IS possible to, at runtime, retrieve, after a ton of hoops and tricky code,
Number.class
andList.class
. But, you shouldn't do this, this is generics abuse. What if someone wrote:Because that would compile fine, and your plan of: I will use reflection to check the actual type bound and use that to at runtime dispatch some stuff - won't work here. All you'll ever be able to tell at runtime here is that the name is 'T', its lower bound is 'Y', and 'Y' is a boundless type param of the enclosing type.