开发者

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:

  1. List a = new ArrayList();

  2. List <?> b = a;

  3. List <? extends Object> c = a; // with warning of course

    for (Object obj : b) {}
    // I don't agree with your statements above that &lt;?&gt; 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:

  1. 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).
  2. 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜