
Why do we need "? extends" in Java - rocky_ex
http://stackoverflow.com/questions/9810445/listmapstring-string-vs-list-extends-mapstring-string
======
democracy
There is a good free tutorial on generics:
<https://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf>. It explains the
design of generics, and tells a bit about why Sun engineers came up with this
implementation.

------
guard-of-terra
When we hire developers with proficiency in Java that's one of our common
interview questions. We also seek ability to figure out what "? super" means.

~~~
ootachi
I have a feeling you're going to get a bunch of type theorists instead of
programmers who get things done if you ask about Java's syntax for use-site
contravariance.

~~~
reginaldo
Not true. You'll get, for instance, people who read Effective Java [1], by
Joshua Bloch (who is, IMHO, THE man when it comes to java), and remembered the
PECS mnemonics. PECS stands for producer-extends, consumer-super.

So, to cite the textbook example, say you are implementing a Stack<E>. It will
probably have the methods:

    
    
      public void push(E element);
      public E pop();
    

and, for convenience:

    
    
      public void pushAll(Iterable<? extends E> elements);
      public void popAll(Collection<? super E> destination);
    

The pushAll has "? extends" because the elements Iterable will "produce"
elements for the stack. The popAll has super because the destination
Collection will "consume" elements from the stack. It is not that hard, is it?
Let's note that guard-of-terra is talking about proficiency, not mere
familiarity. I believe reading "Effective Java" is a nice way to get closer to
the proficient level.

Let it be noted that this whole mess exists because generics in Java were
implemented with type erasure so their introduction wouldn't break legacy
code. I personally think this was a bad idea, but it does show that when a
language is evolving, there are a bunch of constraints the designers must be
aware of.

[1] [http://www.amazon.com/Effective-Java-Edition-Joshua-
Bloch/dp...](http://www.amazon.com/Effective-Java-Edition-Joshua-
Bloch/dp/0321356683/ref=sr_1_1?ie=UTF8&qid=1332688982&sr=8-1)

~~~
ootachi
This doesn't seem to have anything to do with type erasure, does it? It's
needed for type-safe generics. Even without type erasure, you still need type
safety. If your generics are always covariant (like Dart's are), you break
type safety.

I think the mistake the Java designers made here was going with use-site
variance instead of definition-site variance.

~~~
reginaldo
Yes, you're right. We're talking about variance when it comes to the "?
extends, ? super" situation, not erasure. And you're also right the things
would be better with definition-site variance.

On the other hand, sometimes I think an unsound type system with List<String>
being a subtype of List<Object> would be better than what we have today, for
pragmatic reasons. Of course, I think this makes me a non-type-theorist, as
what I'm saying is considered heresy in some circles [1].

[1] <http://lambda-the-ultimate.org/node/4377> (search for unsound).

~~~
guard-of-terra
But than you can never get anything from List<String>! Because you never know
what type are you getting!

On the other hand, if your structure is immutable it would probably work.

------
myspy
We had to learn it when doing an oo programming course at university. And I
immediately forgot all about it.

I hope when writing Java code sometimes at a job, I can refer to this again.

This is all done in the name of type safe programming (I don't know the exact
english terminology).

<? extends B> is called covariance. It helps to access attributes of B and
derived classes with get() but prevents to use set().

ArrayList<? extends Number> list;

list = new ArrayList<Integer>();

list = new ArrayList<Double>();

list = new ArrayList<Long>();

list.set(index, myInteger); // throws error

Compiler has to know the exact type to set the value, but Long, Double and
Integer are all from type Number, so you can read it into a Number variable.

Is that correct?

~~~
guard-of-terra
You describe how it works, but not what it means in simple terms.

List<Shape> is not a "list of Shapes", it's a "list parametrized with Shape"

List<? extends Shape> is a "list parametrized with something that extends
Shape"

e.g. you can assign it with List<Circle> (you can't assign it to List<Shape>
since Shape != Circle) and then you can do operations on it that would not
break List<Circle> (can't put Square in it)

~~~
myspy
Great, thank you. It's interesting to learn, when you don't know how to
describe something in simple terms. I blame my lacking college professor and
me, not taking enough time to learn it properly.

------
gaving
Why do we need Java?

~~~
prodigal_erik
Currently, the JVM usually outperforms everything other than C or C++, and
those are only fast until they blow up randomly because humans can't write
100% flawless code.

~~~
zxcvb
I don't know about that. Some of the Java libraries that were written in C
were long ago converted to Java and they run faster.

It's hard to say that the JVM is faster or slower than X because it usually
comes down to the way in which the application is developed.

If C++ was ALWAYS faster then I wouldn't be using Java for our trading
systems. Some of our competitors use C++ and some use Java. We have one of the
fastest trading platforms in the world, the only firm to have faster than us
are also using Java.

~~~
prodigal_erik
Cool. I've always expected JIT could eventually beat AOT compilation, though I
haven't heard of that being commonly seen. I'm a little surprised that C++
still tends to use crude vtable dispatch just because that's what Stroustrup
demonstrated and it's easy.

------
H_E_Pennypacker
All about Java Generics in one big FAQ

------
ssdsa
Wow, I'm so glad that I don't need to worry about such a mess when using duck-
typing in Python.

~~~
yummyfajitas
I'm glad that when I refactor code in Java, the type checker catches many of
my mistakes. Not as many as in Haskell, but still.

In Python, the deploy/run unit tests/spot typo cycle greatly slows me down.

~~~
Mavrik
Yeah this... I've found out that I subconsciously actively avoid refactoring
our (old and in parts terrible) codebase because the tools for it are so bad.

------
ronreiter
I thought the whole point about Java is that it's supposed to be extra verbose
(which is also the reason it sucks a bit). wtf is this shit

~~~
guard-of-terra
Let me tell you why everyone is downvoting you:

The "? extends" is not an "extra verbosity". It's actually a sound CS concept,
one that you need to make compiler understand how some generic code turns out
to be correct while working on partially specified types.

IIRC C# didn't have that "extra verbose" thing in its early versions and the
developers weren't very happy because you do need it.

Not being able to separate "extra verbosity" from "solid CS concepts" makes
you lousy at reasoning about programming languages. Might as well stop
bothering.

