Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><em>Sorry, but you can't.</em></p> <p>The wildcard declaration of <code>List&lt;? extends Number&gt; foo3</code> means that the variable <code>foo3</code> can hold any value from a family of types (rather than any value of a specific type). It means that any of these are legal assignments:</p> <pre><code>List&lt;? extends Number&gt; foo3 = new ArrayList&lt;Number&gt;; // Number "extends" Number List&lt;? extends Number&gt; foo3 = new ArrayList&lt;Integer&gt;; // Integer extends Number List&lt;? extends Number&gt; foo3 = new ArrayList&lt;Double&gt;; // Double extends Number </code></pre> <p>So, given this, what type of object could you add to <code>List foo3</code> that would be legal after any of the above possible <code>ArrayList</code> assignments:</p> <ul> <li>You can't add an <code>Integer</code> because <code>foo3</code> could be pointing at a <code>List&lt;Double&gt;</code>.</li> <li>You can't add a <code>Double</code> because <code>foo3</code> could be pointing at a <code>List&lt;Integer&gt;</code>.</li> <li>You can't add a <code>Number</code> because <code>foo3</code> could be pointing at a <code>List&lt;Integer&gt;</code>.</li> </ul> <p><strong>You can't add any object to <code>List&lt;? extends T&gt;</code> because you can't guarantee what kind of <code>List</code> it is really pointing to, so you can't guarantee that the object is allowed in that <code>List</code>. The only "guarantee" is that you can only read from it and you'll get a <code>T</code> or subclass of <code>T</code>.</strong></p> <p>The reverse logic applies to <code>super</code>, e.g. <code>List&lt;? super T&gt;</code>. These are legal:</p> <pre><code>List&lt;? super Number&gt; foo3 = new ArrayList&lt;Number&gt;; // Number is a "super" of Number List&lt;? super Number&gt; foo3 = new ArrayList&lt;Object&gt;; // Object is a "super" of Number </code></pre> <p><strong>You can't read the specific type T (e.g. <code>Number</code>) from <code>List&lt;? super T&gt;</code> because you can't guarantee what kind of <code>List</code> it is really pointing to. The only "guarantee" you have is you are able to add a value of type <code>T</code> (or any subclass of <code>T</code>) without violating the integrity of the list being pointed to.</strong></p> <hr> <p>The perfect example of this is the signature for <code>Collections.copy()</code>:</p> <pre><code>public static &lt;T&gt; void copy(List&lt;? super T&gt; dest,List&lt;? extends T&gt; src) </code></pre> <p>Notice how the <code>src</code> list declaration uses <code>extends</code> to allow me to pass any List from a family of related List types and still guarantee it will produce values of type T or subclasses of T. But you cannot add to the <code>src</code> list.</p> <p>The <code>dest</code> list declaration uses <code>super</code> to allow me to pass any List from a family of related List types and still guarantee I can write a value of a specific type T to that list. But it cannot be guaranteed to read the values of <strong>specific</strong> type T if I read from the list.</p> <p>So now, thanks to generics wildcards, I can do any of these calls with that single method:</p> <pre><code>// copy(dest, src) Collections.copy(new ArrayList&lt;Number&gt;(), new ArrayList&lt;Number()); Collections.copy(new ArrayList&lt;Number&gt;(), new ArrayList&lt;Integer()); Collections.copy(new ArrayList&lt;Object&gt;(), new ArrayList&lt;Number&gt;()); Collections.copy(new ArrayList&lt;Object&gt;(), new ArrayList&lt;Double()); </code></pre> <hr> <p>Consider this confusing and very wide code to exercise your brain. The commented out lines are illegal and the reason why is stated to the extreme right of the line (need to scroll to see some of them):</p> <pre><code> List&lt;Number&gt; listNumber_ListNumber = new ArrayList&lt;Number&gt;(); //List&lt;Number&gt; listNumber_ListInteger = new ArrayList&lt;Integer&gt;(); // error - can assign only exactly &lt;Number&gt; //List&lt;Number&gt; listNumber_ListDouble = new ArrayList&lt;Double&gt;(); // error - can assign only exactly &lt;Number&gt; List&lt;? extends Number&gt; listExtendsNumber_ListNumber = new ArrayList&lt;Number&gt;(); List&lt;? extends Number&gt; listExtendsNumber_ListInteger = new ArrayList&lt;Integer&gt;(); List&lt;? extends Number&gt; listExtendsNumber_ListDouble = new ArrayList&lt;Double&gt;(); List&lt;? super Number&gt; listSuperNumber_ListNumber = new ArrayList&lt;Number&gt;(); //List&lt;? super Number&gt; listSuperNumber_ListInteger = new ArrayList&lt;Integer&gt;(); // error - Integer is not superclass of Number //List&lt;? super Number&gt; listSuperNumber_ListDouble = new ArrayList&lt;Double&gt;(); // error - Double is not superclass of Number //List&lt;Integer&gt; listInteger_ListNumber = new ArrayList&lt;Number&gt;(); // error - can assign only exactly &lt;Integer&gt; List&lt;Integer&gt; listInteger_ListInteger = new ArrayList&lt;Integer&gt;(); //List&lt;Integer&gt; listInteger_ListDouble = new ArrayList&lt;Double&gt;(); // error - can assign only exactly &lt;Integer&gt; //List&lt;? extends Integer&gt; listExtendsInteger_ListNumber = new ArrayList&lt;Number&gt;(); // error - Number is not a subclass of Integer List&lt;? extends Integer&gt; listExtendsInteger_ListInteger = new ArrayList&lt;Integer&gt;(); //List&lt;? extends Integer&gt; listExtendsInteger_ListDouble = new ArrayList&lt;Double&gt;(); // error - Double is not a subclass of Integer List&lt;? super Integer&gt; listSuperInteger_ListNumber = new ArrayList&lt;Number&gt;(); List&lt;? super Integer&gt; listSuperInteger_ListInteger = new ArrayList&lt;Integer&gt;(); //List&lt;? super Integer&gt; listSuperInteger_ListDouble = new ArrayList&lt;Double&gt;(); // error - Double is not a superclass of Integer listNumber_ListNumber.add(3); // ok - allowed to add Integer to exactly List&lt;Number&gt; // These next 3 are compile errors for the same reason: // You don't know what kind of List&lt;T&gt; is really // being referenced - it may not be able to hold an Integer. // You can't add anything (not Object, Number, Integer, // nor Double) to List&lt;? extends Number&gt; //listExtendsNumber_ListNumber.add(3); // error - can't add Integer to *possible* List&lt;Double&gt;, even though it is really List&lt;Number&gt; //listExtendsNumber_ListInteger.add(3); // error - can't add Integer to *possible* List&lt;Double&gt;, even though it is really List&lt;Integer&gt; //listExtendsNumber_ListDouble.add(3); // error - can't add Integer to *possible* List&lt;Double&gt;, especially since it is really List&lt;Double&gt; listSuperNumber_ListNumber.add(3); // ok - allowed to add Integer to List&lt;Number&gt; or List&lt;Object&gt; listInteger_ListInteger.add(3); // ok - allowed to add Integer to exactly List&lt;Integer&gt; (duh) // This fails for same reason above - you can't // guarantee what kind of List the var is really // pointing to //listExtendsInteger_ListInteger.add(3); // error - can't add Integer to *possible* List&lt;X&gt; that is only allowed to hold X's listSuperInteger_ListNumber.add(3); // ok - allowed to add Integer to List&lt;Integer&gt;, List&lt;Number&gt;, or List&lt;Object&gt; listSuperInteger_ListInteger.add(3); // ok - allowed to add Integer to List&lt;Integer&gt;, List&lt;Number&gt;, or List&lt;Object&gt; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload