4

Why does the compiler issue a warning when declaring a variable as

 List<? extends Object> list = new LinkedList();

Warning:

Note: ZiggyTest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

But it doesnt issue a warning when i declare the variable as

List<?> list = new LinkedList();
ziggy
  • 15,677
  • 67
  • 194
  • 287
  • Checkout http://stackoverflow.com/questions/8683137/and-extends-object/8683314 and the excellent generics tutorial in my answer there which is a must-read when working with generics – Robin Jan 01 '12 at 21:48
  • It isn't issuing any waning as you have mentioned in my NetBeans 6.9.1 with jdk 6. – Lion Jan 01 '12 at 22:01
  • I am not using an IDE. Do you get the warnings when you compile from the command line prompt? – ziggy Jan 01 '12 at 22:15
  • Yes, I tried from the *command-line* and it issued the warning as you say. When I modified your statement like `List extends Object> list = new LinkedList();`, it compiled with no warning. Give it a try. – Lion Jan 01 '12 at 22:24
  • I was interested in the reason as to why the warnings are generated in the first example and not in the second. I know that when i specify the type on the right and left then there wont be any warnings. – ziggy Jan 01 '12 at 22:28
  • The reason has been mentioned in my following answer. ***"It means that the compiler can't check that you're using the collection in a type-safe manner."*** To avoid that warning, we should mention the exact *generic type* `` the collection is using. – Lion Jan 01 '12 at 22:31
  • It's a minor flaw in spec. `List>` and `List extends Object>` are equivalent types, but spec treats them differently sometimes. – irreputable Jan 01 '12 at 23:53

2 Answers2

2

This comes up in Java 5 and later if you're using collections without type specifiers (e.g., Arraylist() instead of ArrayList<String>()). It means that the compiler can't check that you're using the collection in a type-safe manner, using generics.

To get rid of the warning, just be specific about what type of objects you're storing in the collection. So, instead of

List list = new ArrayList();

should be as

List<String> list = new ArrayList<String>();

In your case, if you modify that statement as follows,

List<? extends Object> list = new LinkedList<Object>();

it would compile with no warning because we are now making it type-safe using the generic type (<Object>).

Lion
  • 18,729
  • 22
  • 80
  • 110
1

I cannot explain why the compiler won't treat these as equivalent, but given that it does not, I'll attempt to explain why it refuses to do so.

The first one (List<? extends Object>) asserts that the type of objects held in the List are of some unknown type derived from Object. The second one (List<?>) says less; it merely says that the type of the objects in the list is unknown. It doesn't mention any expected supertype as the upper bound of the unknown type.

In order to verify the first assumption, the compiler wants to hear you say something about the expected types held in the List instance constructed here as the raw type LinkedList, which says nothing on the subject. However, if you were to construct the instance as type LinkedList<Object>, you're at least guaranteeing that covariant reads against the instance will be consistent with your assertion: namely, that the things in this list are some kind of Object.

Now, this all seems silly, because every reference/non-primitive type in Java extends Object, so there shouldn't be any difference in interpretation between List<? extends Object> and List<?>; after all, the second one implies the first one, by virtue of the language's type system's mandated singly-rooted class hierarchy.

seh
  • 14,999
  • 2
  • 48
  • 58