I have the following method:
public <U, V> boolean isEqual(List<U> a, List<V> b) {
// check if U == V
}
I want to check if U
and V
are the same classes.
You can't do that because of type erasure, it is that simple.
Consider the following:
public static void main(String[] args) {
List<? extends Number> l1 = Arrays.asList(1L, 2, 3L);
List<? extends Number> l2 = Arrays.asList(1);
isEqual(l1, l2);
}
public static <U, V> boolean isEqual(List<U> a, List<V> b) {
// is U == V here?
}
Is U == V
here? l1
contains Long
and Integer
instances but l2
contains a single Integer
instance.
I'm guessing from your comment:
The first condition should be that their type are the same
that what you should have instead is a single type U
. In this case, use the following signature:
public static <U> boolean isEqual(List<U> a, List<U> b) {
}
and with that, the above code won't compile anymore.
What you could also do is add 2 parameters accepting the classes:
public static <U, V> boolean isEqual(List<U> a, List<V> b, Class<U> uClass, Class<V> vClass) {
if (!uClass.equals(vClass)) {
// classes are different
}
}
In this case, you can print a message if the classes given are not the same.
If you are making your own class you can require that Class<T>
be included in the constructor as demonstrated here
Ex:
public class SomeClass<T> {
private final Class<T> clazz;
public SomeClass(Class<T> clazz) {
this.clazz = clazz;
}
public Class<T> getParam() {
return clazz;
}
}
Now you can call SomeClass#getParam()
to get the type param declared.
There is also a way to do this with reflection.
All this said, the reason you have to do weird work-arounds to this is because of Type Erasure. Basically at runtime Java sees all generics as Object
, so while compiling your List
may be a List<Integer>
or List<Boolean>
, but at runtime they're both List<Object>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With