Raw to <? extends Object>
I just don't understand this.
List list = new ArrayList();
List <? extends Object> list1 = list; // unchecked conversion warning.
Since Object
is the highest upper bound in Java, I don't see any reason why the warning is there.
Update 1:
With regard to akf's answer:
I understand perfectly what you are saying. I already know that.
But <? extends Object>
is the highest upper bound. Which means you are have any type too you wa开发者_开发知识库nt. Basically <?> == <? extends Object>
.
You can try this on your code and you will see <?> == <? extends Objects>
Update 2:
With regard to Sheng's answer:
List list = new ArrayList ();
List.add("a");
List <? extends Runnable> list1 = list; //warning here
Why no warning here?
List <?> list2 = list; // No warning here
Update 3:
I'm just revisiting the above and still puzzled.
Since the following is permitted by the compiler:
List a = new ArrayList();
List <?> b = a;
List <? extends Object> c = a; // with warning of course
for (Object obj : b) {} // I don't agree with your statements above that <?> cannot be // written in the for (:) loop as shown here for (Object obj : c) {}
Both are permissible. So i still don't see why the unchecked warning when assiging raw to <? extends Object>
This question, and in particular this answer, have some more details on the differences between ?
and ? extends Object
. I still haven't found anything that says why you get a warning assigning from List
to List<? extends Object>
, though.
If I'm thinking correctly, then by default the compiler assumes you mean this
List<?> list = new ArrayList();
The ? means that you can have any generic type you want. This is why
List list = new ArrayList();
List <?> list2 = list
works, because for the compiler they are the same thing
However, when you do this
List<?> list = new ArrayList();
List<? extends Object> list2 = list
You're limiting its scope. Because you are limiting the scope, you get a warning. Yes, I know that you don't think you are, but to the compiler you are. If you're absolutely sure you know what your doing, just ignore it or suppress it
Assume if we use Runnable
instead of Object
in list1. It's compile ok, but runtime error:
List list = new ArrayList ();
list.add("a");
List <? extends Runnable> list1 = list;
for(Runnable o:list1){ //Runtime exception-> java.lang.ClassCastException
o.run();
}
The case shows the potential problem, this is why warning here.
But your IDE just checks the syntax List <? extends SomeType>
, no matter SomeType is an Object
or something else.
I think Shengyuanl Lu has already explained it precisely. I would add that whenever you see such a thing, just recall these two following points:
- You can't just cast a container of "any type" to a container of "bounded type" (no matter if the former is bounded to Object type).
- Whenever you do it, you create "heap pollution"(refer to Angelika Langer's Java Generics FAQ's for description)
I believe this happens because of the way Java handles Bounded Wildcards, in that List<? extends Object> is not the same nor a subclass of List
Originally the concept somewhat confusing to me as well, and I found Generics in the Java Programming Language document extremely useful in understanding specifically these kinds of Generics.
精彩评论