To my understanding, <? extends Object>
and <?>
are same.
However, when I run the following code <? extends Object>
does not get compiled and is working as expected but <?>
is getting compiled successfully.
public class Test1
{
interface I1
{
}
interface I2<T extends I1> extends Comparable<I2<?>>
{
Comparator<I2<? extends I1>> A = null;
//Comparator<I2<? extends Object>> B = A; // expected compilation fail
Comparator<I2<?>> B = A; // compiling successfully.This shouldn't get compile
}
}
Can some one help me understand this behavior.
extends Number> represents a list of Number or its sub-types such as Integer and Double. Lower Bounded Wildcards: List<? super Integer> represents a list of Integer or its super-types Number and Object.
From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). A generic method differs from an ordinary method in the same way.
extends Object> means you can pass an Object or a sub-class that extends Object class.
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)
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