title: Why does Java Collector.toList() require a wildcard type placeholder in its return type?
body: <p>I've been doing some Java Streams manipulation, and of course it doesn't like my code and is refusing to provide useful error messages. (For reference, I have no problems whatsoever with C# and Linq, so I understand conceptually everything I'm trying to do.) So I started digging into adding the explicit generic types to every method in my code so I can find the source of the problem, as past experience tells me that this is a successful path forward.</p>
  
  <p>While looking around I ran across something I don't understand. Consider the following code from the Java source (reformatted a little bit):</p>
  
  <pre><code>public static &lt;T&gt; Collector&lt;T, ?, List&lt;T&gt;&gt; toList() {
      return new Collectors.CollectorImpl&lt;&gt;(
          (Supplier&lt;List&lt;T&gt;&gt;) ArrayList::new,
          List::add,
          (left, right) -&gt; {
               left.addAll(right);
               return left;
          },
          Collectors.CH_ID
      );
  }
  </code></pre>
  
  <p>Why does the <code>toList</code> method signature require a wildcard <code>?</code> in its return type? When I remove it, I get</p>
  
  <blockquote>
  <pre><code>Wrong number of type arguments: 2; required: 3
  </code></pre>
  </blockquote>
  
  <p>and</p>
  
  <blockquote>
  <pre><code>Incompatible types.
  Required: Collector&lt;T, List&lt;T&gt;, &gt;
  Found: CollectorImpl&lt;java.lang.Object, List&lt;T&gt;, java.lang.Object&gt;
  </code></pre>
  </blockquote>
  
  <p>When I change <code>?</code> to <code>Object</code>, I get (referring to these lines/methods in the above code):</p>
  
  <blockquote>
  <pre><code>List::add – Cannot resolve method 'add'
  left.addAll – Cannot resolve method 'addAll(java.lang.Object)'
  </code></pre>
  </blockquote>
  
  <p>When I put the wildcard back and examine these two, they are:</p>
  
  <blockquote>
  <pre><code>List – public abstract boolean add(T e)
  List – public abstract boolean addAll(Collection&lt;? extends T&gt; c)
  </code></pre>
  </blockquote>
  
  <p>Further fiddling around hasn't taught me anything more.</p>
  
  <p>I understand that in one scenario such as the <code>? extends T</code>, the wildcard in Java can be translated over to C# as a new generic type argument with a <code>where TWildCard : T</code>. But what is going on with <code>toList</code> above, where the return type has a bare wildcard?</p>