I have an interface that contains methods that return or require instances of the imlementing type. To accomplish this I create a type variable of the form U extends I<U>
to use as the return type. The intention of course being that U
is the implementing class:
interface SelfReferringInterface<U extends SelfReferringInterface<U>> {
}
Now I have an implementing class that contains an unrelated type variable:
class RestrictingType<T> implements SelfReferringInterface<RestrictingType<T>> {
}
And a class that wraps around an instance of a SelfReferringInterface
:
class Wrapper<T extends SelfReferringInterface<T>> {
}
Somehow I get a type inference error for Wrapper
types that take a wild card instance of RestrictingType
:
public class Main {
public static void main(String... args) {
// This type checks
SelfReferringInterface<?> test1;
// This too
RestrictingType<?> test2;
// And this
Wrapper<RestrictingType<Object>> test3;
// This fails
Wrapper<RestrictingType<?>> test4;
// Interestingly this does succeed
Wrapper<? extends RestrictingType<?>> test5;
}
}
Compiling this gives the following error:
Main.java:23: error: type argument RestrictingType<?> is not within bounds of type-variable T
Wrapper<RestrictingType<?>> test4;
^
where T is a type-variable:
T extends SelfReferringInterface<T> declared in class Wrapper
1 error
Why is RestrictingType<?>
not within the bounds of T
? And why is the functionaly similar ? extends RestrictingType<?>
no problem?
Wrapper<RestrictingType<T>>
works for any given type T
because we know that Restricting<T>
implements SelfReferringInterface<RestrictingType<T>>
. However, Wrapper<RestrictingType<?>>
does not work because Restricting<? #1>
may not implement SelfReferringInterface<RestrictingType<? #2>>
. The wildcard ?
means unknown type, and they may be two different unknown types in the two places.
Here is another way to see why this must be: Suppose that your Wrapper<T>
class can hold multiple items of the wrapped type T
. Then the bound <T extends SelfReferringInterface<T>>
means that the type of any one of the items should implement SelfReferringInterface<type of any other item>
, just like how class SortedList<T extends Comparable<T>>
means that any one item in the list should be comparable to any other item in the list. However, if you have a Wrapper<RestrictingType<?>>
, you will be able to add both RestrictingType<String>
and RestrictingType<Integer>
items into it, as both those types are subtypes of RestrictingType<?>
. However, RestrictingType<String>
does not implement SelfReferringInterface<RestrictingType<Integer>>
, so the contract is broken.
As to why Wrapper<? extends RestrictingType<?>>
works, I am not really sure exactly, but the ? extends
wildcard means you cannot add any items into it, so you cannot use it to break the contract.