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 whichgetClass
is 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