0

Consider the following code:

List<? extends Integer> lst= new ArraList<Integer>();
lst.add(5);//Compile error
lst.get(5);//OK

In the second string we have compile error, because we must guaranted have method add(int) in all potencial subtypes of List<? extends Integer> and compiler know that its null only, third string returns unknow type and compiler cast him to Object, isnt it?

St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • possible duplicate of [Java Generics: What is PECS?](http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs) – Rohit Jain Sep 24 '13 at 19:18
  • FYI, [`List#get(int)`](http://docs.oracle.com/javase/7/docs/api/java/util/List.html#get(int)) takes an index. – Rohit Jain Sep 24 '13 at 19:18
  • Considering `Integer` is `final`, `? extends Integer` is not useful. – luiscubal Sep 24 '13 at 19:20
  • @RohitJain :) Hey, you keep spoiling my game :)) And you spoil my game before I'd type it, so now I seem to be a plagiarist... – ppeterka Sep 24 '13 at 19:20
  • @ppeterka66. Ah! I'll not do it again. ;) – Rohit Jain Sep 24 '13 at 19:21
  • @RohitJain no offense, of course ;) it's just so funny I write something, refresh, and there it is in the comments :) – ppeterka Sep 24 '13 at 19:22
  • @luiscubal It can be useful (if verbose) marker that a collection is intended to be read-only. Plus, sometimes an API will give you a `List extends T>` and doesn't care if `T` is final, so it's still useful to understand, even if the specific use case here is a bit forced (as many concise examples tend to be). – yshavit Sep 24 '13 at 19:42

3 Answers3

1

PECS. Producer extends, Consumer super.

List<? super Integer> lst= new ArrayList<Integer>();
lst.add(5);// No Compile error

The list is a consumer now, you put objects into it...

Also this

lst.get(5);

Is a different cake... You provide the Integer index of which you want to get... (Not to mention what Sotirios mentioned: the return type will be Object in this case. Also, in this role, the list is a provider...)

Community
  • 1
  • 1
ppeterka
  • 20,583
  • 6
  • 63
  • 78
  • 1
    Note that with the above, `lst.get(x)` returns an object of type `Object`, so you will probably need to cast it. – Sotirios Delimanolis Sep 24 '13 at 19:31
  • @SotiriosDelimanolis that is true, and also, the issue is that the list is a provider in that case... So applying the intersection of the two (the `? extends Integer` and the `? super Integer` sets) leaves the exact `Integer` type to be used in this example... – ppeterka Sep 24 '13 at 19:35
0

You cannot add anything except null to a List bounded by a wildcard because you never know the underlying type.

List<? extends Integer> lst= new ArrayList<Integer>();
lst.add(5); // Compile error
lst.get(5); // 5 is just the index

You can however get an element because you know it must be an Integer (in this case).

It's hard to explain with Integer because it's a class that cannot be extended. But take this

public class Foo {}

public class Bar extends Foo {}

public class Zoop extends Foo {}

What could you add to

List<? extends Foo> fooList = new ArrayList<Zoop>(); // could come from a method

?

The list is declared as ? extends Foo even though the runtime object's generic type is Zoop. The compiler therefore cannot let you add anything. But you are guaranteed to be operating on Foo objects, so you can retrieve them fine.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
0

Once you have a List<? extends Integer>, the compiler doesn't know whether it's Integer or a subtype. The compiler can't ensure the type safety of adding anything except null (really, passing anything to a method taking a generic type parameter, including the add method), so it disallows it. This occurs despite the fact that Integer is final and no subclasses are allowed.

For the get method, the compiler knows that the return type is some kind of Integer, so it allows the call and places an implicit cast to Integer.

rgettman
  • 176,041
  • 30
  • 275
  • 357