2

I often encounter situations like:

List<Fooable> fooList;

vs

List<? extends Fooable> fooList;

What is the difference between these two? Or is there a name for this / pre-existing link where this difference is described? I can't Google this concept because I don't know what it's called or how else you'd describe this.

Does it matter if Fooable is an interface? A concrete class? An abstract class? Does this only apply to classes that extend and/or implement something?

AJJ
  • 1,794
  • 3
  • 22
  • 34
  • 2
    I believe that is answered here. http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java – OneCricketeer Oct 17 '16 at 20:09
  • Or here. http://programmers.stackexchange.com/questions/303584/what-is-the-difference-between-extends-foo-and-foo – OneCricketeer Oct 17 '16 at 20:10
  • As for the name of that construct, it is called "upper bounded wildcard", see for example https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html – user140547 Oct 17 '16 at 20:10
  • @cricket_007, the proposed duplicate doesn't really answer OP's question. To me, it's clear that this question is about whether types `` and ` extends Fooable>` are interchangeable, and not about bounded wildcards in general. – Mick Mnemonic Oct 17 '16 at 20:17
  • @user140547 This was helpful, in particular this sentence: `The term List is more restrictive than List extends Number> because the former matches a list of type Number only, whereas the latter matches a list of type Number or any of its subclasses.` – AJJ Oct 17 '16 at 20:22
  • So `List` literally means the list contains `Animal` objects -- not `Cats` or `Dogs`, but literally `Animals`. If I wanted a list including `Cats` and `Dogs` I'd have `List extends Animal>` assuming we have `Cat extends Animal` or `Dog extends Animal`. Does this matter whether `Cat` is extending or implementing `Animal`? – AJJ Oct 17 '16 at 20:23
  • I think if there was a concrete example that you've ran into the differences might become more apparent. And no that's not what it means. A list of Animals (`List`) can indeed hold Cats and Dogs. I would try some code and observe the uses. – ChiefTwoPencils Oct 17 '16 at 20:23
  • 1
    Actually, the linked question on Programmers SO does seem like a duplicate. – Mick Mnemonic Oct 17 '16 at 20:24
  • 1
    That's not what the Java link says though? `the former matches a list of type Number only` – AJJ Oct 17 '16 at 20:26
  • Well, I'm not sure how you're understanding it. I don't want to add an answer when the first link is so well done but you have nearly an opposite understanding of what is true. Quickly write those classes (yes Animal can be an interface) and then try to add some animals to the two types of lists you have. It's not going to behave as you say. – ChiefTwoPencils Oct 17 '16 at 20:32
  • I am literally going from what the Java link says. How is my understanding the opposite? Is the Java link wrong? – AJJ Oct 17 '16 at 20:35
  • It's opposite because you're saying `List` must *not* contain Cats or Dogs but that's not true; that's basic polymorphic behavior and makes sense since Cats and Dogs *are* Animals. – ChiefTwoPencils Oct 17 '16 at 20:37
  • Makes sense to me intuitively, but if `List` can contain Cats and Dogs, what about `List extends Animal>`? Does that list also contain Cats and Dogs? If so, how are the lists different in what they can do? – AJJ Oct 17 '16 at 20:37
  • Read the newly added answer please. – ChiefTwoPencils Oct 17 '16 at 20:39

1 Answers1

1

Well if there is no duplicate...

A List<Animal> can contain Cats and Dogs. You can add Cats and Dogs to the list. It does not mean it can only contain Animals.

But if you have a method foo(List<Animal> foo), you can not pass a List<Cat> to it. But you can add Cats, Dogs or Animals to the passed List<Animal>.

If you have a foo(List<? extends Animal> foo), you can pass a List<Animal>,List<Dog>, and List<Cat> to it and read from it, i.e. you can access Animals methods.

But since any List of subtype of Animal may be passed to it (you don't know which type, it may be an Animal, a Cat or a Dog, or some totally different Animal, you cannot add any elements (except null) to it.

user140547
  • 6,545
  • 2
  • 21
  • 63
  • Is it an arbitrary restriction? I would have assumed that `foo(List foo)` would accept `List` since Cat is an Animal – AJJ Oct 17 '16 at 20:39
  • see https://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p – user140547 Oct 17 '16 at 20:42
  • So basically, the answer is that Java's generics work in a very counter-intuitive way. – Mick Mnemonic Oct 17 '16 at 20:50
  • Also, I found a [duplicate](http://stackoverflow.com/questions/17834145/whats-the-use-of-saying-extends-someobject-instead-of-someobject/17834223). – Mick Mnemonic Oct 17 '16 at 20:54