This question is actually interesting but not asked clearly, which easily makes people think it is a duplicate.
First, an example which I think most people here should understand why it does not work:
class Foo<T> {} class Bar<T> {} class Parent{} public class Test1 { public static void main(String[] args) { Foo<Bar<? extends Parent>> a = null; Foo<Bar<? extends Object>> b = a; // does not compile Foo<Bar<?>> c = a; // does not compile } }
It is obvious: a Foo<Bar<?>> / Foo<Bar<? extends Object>> is not convertible to Foo<Bar<? extends Parent>> (To simply: just like you cannot assign List<Dog> to List<Animal> reference.)
However, in the question you can see the case of Comparator<I2<?>> B = A; does compile, which is contradict with what we see above.
The difference, as specified in my example will be:
class Foo<T> {} class Bar<T extends Parent> {} class Parent{} public class Test1 { public static void main(String[] args) { Foo<Bar<? extends Parent>> a = null; Foo<Bar<? extends Object>> b = a; // does not compile Foo<Bar<?>> c = a; // COMPILE!! } }
By changing class Bar<T> to class Bar<T extends Parent> created the difference. It is a pity that I still cannot find the JLS section that is responsible on this, but I believe it when you declare a generic class with bound in type parameter, the bound is implicitly carried to any wildcard you use against that.
Therefore, the example become:
class Foo<T> {} class Bar<T extends Parent> {} class Parent{} public class Test1 { public static void main(String[] args) { Foo<Bar<? extends Parent>> a = null; //... Foo<Bar<? extends Parent>> c = a; } }
which explain why this compile.
(Sorry I cannot find evidence this is how the language is designed. It will be great if someone can find in JLS for this)
I2of something extendsI1can be called anI2of something. (In contrast, anI2of something extendsI1can only be called anI2of something extendsObjectbecause we know thatI1must be a subclass ofObject, which is a conclusion I'm guessing the java compiler isn't willing to jump to.)