I have a function:
<T> T get(Class<T> fetchType) {
...
}
So, if I were to do something like:
String x = get(String.class);
this is all good.
However, in another function:
<R> R otherFunction(R base) {
return get(base.getClass());
}
Gives me an error, because base.getClass() returns ? extends R.
reason: no instance(s) of type variable(s) exist so that capture of ? extends Object conforms to R
inference variable T has incompatible bounds:
equality constraints: capture of ? extends Object upper bounds: Object, R
Now from what I understand, the function get(Class<T> x) returns T, so when called with ? extends R, which let's say is CAP#1, but since get now returns CAP#1, assigning it to type R should not be a problem. To test this, I tried:
Class<? extends CharSequence> stringClass = String.class;
CharSequence x = get(stringClass);
This seems to work without any issues. What's going wrong?
EDIT: Is this because of type-erasure, that at runtime no information about R is available, but CharSequence is? Which still doesn't make sense because isn't this purely checked during the compile phase alone?
So, it turns out thatObject.getClass() returns Class<? extends |X|> and not Class<? extends X>, where |X| is the erasure of X which is why it works for concrete types (like ? extends CharSequence, but not for a generic type). IntelliJ probably does not report it accurately, which caused the confusion:
(I tried taking a screenshot, but the pop-up kept on going away).
The reason is described in the Javadoc of Object.getClass:
public final Class<?> getClass()The actual result type is
Class<? extends |X|>where|X|is the erasure of the static type of the expression on whichgetClassis called.
So, when you call base.getClass(), the actual result is Class<?>, since the erasure of R is Object. It's not Class<? extends R>.
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