Some example code:
public class Main {
class SomeType {
}
class A {
protected <T extends SomeType> T createSomething()
{
return null; // Don't worry about this.
}
}
class B extends A {
@Override
protected <T extends SomeType> T createSomething()
{
SomeType orig = super.createSomething();
// do some stuff with orig
return orig;
}
}
}
What am I getting wrong here?
On the line
return orig;
the compiler spits out the error that
Type mismatch: cannot convert from Main.SomeType to T
Thanks to <T extends SomeType>
, we can be sure that T
is always a subtype of SomeType
, right? So why can't I just return the supertype SomeType
?
I've already read <? extends SuperType> cannot be applied to SuperType and Explanation of the get-put principle but I don't see how it applies here.
Thanks to
<T extends SomeType>
, we can be sure thatT
is always a subtype ofSomeType
, right?
Right.
So why can't I just return the supertype
SomeType
?
Because it might not be a T
!
Put it this way - imagine SomeType
is Object
, and T
is String
. You're suggesting that this code should work:
String foo() {
return new Object();
}
It works the other way round - you can return a subtype reference for a method declared to return a supertype, but that's different.
The fix is easy though - just change orig
to be of type T
:
T orig = super.createSomething();
Then it compiles with no problems.
See more on this question at Stackoverflow