Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You're getting an error because a <code>Pair&lt;String, Future&lt;String&gt;&gt;</code> is not a <code>Pair&lt;String, Future&lt;?&gt;&gt;</code>. Generic types are not covariant.</p> <p>You can however type <code>futureTasks</code> as <code>List&lt;Pair&lt;String, ? extends Future&lt;?&gt;&gt;&gt;</code>. Then you'll be able to add a <code>Pair&lt;String, Future&lt;String&gt;&gt;</code> to it.</p> <p><strong>EDIT:</strong></p> <p>To explain this better, think of trying to assign an object to a variable instead of adding it to a list. If we have a <code>List&lt;T&gt;</code>, we can only add an object if it <em>is a</em> <code>T</code>. So this is really the same situation:</p> <pre><code>Pair&lt;String, Future&lt;String&gt;&gt; pairOfStringAndFutureOfString; Pair&lt;String, Future&lt;?&gt;&gt; pairOfStringAndFutureOfSomething; // incompatible types pairOfStringAndFutureOfSomething = pairOfStringAndFutureOfString; </code></pre> <p>Again, this isn't allowed because generics aren't covariant. Why? Consider what could happen if they were:</p> <pre><code>Future&lt;Integer&gt; futureOfInt; Future&lt;?&gt; futureOfSomething; futureOfSomething = futureOfInt; // a future of int is a future of something Pair&lt;String, Future&lt;String&gt;&gt; pairOfStringAndFutureOfString; Pair&lt;String, Future&lt;?&gt;&gt; pairOfStringAndFutureOfSomething; // pretend this is legal pairOfStringAndFutureOfSomething = pairOfStringAndFutureOfString; // danger! pairOfStringAndFutureOfSomething.setRight(futureOfSomething); Future&lt;String&gt; futureOfString = pairOfStringAndFutureOfString.getRight(); //sometime later... String string = futureOfString.get(); //ClassCastException </code></pre> <p>We got <code>futureOfString</code> to point to something that was actually a <code>Future&lt;Integer&gt;</code>. But this didn't even cause a <code>ClassCastException</code> right away because thanks to type erasure, the JVM only saw <code>Future</code>s. This situation is called "heap pollution" - where a variable points to an object it shouldn't have been allowed to. The actual runtime error only happened once we tried to unwrap <code>futureOfString</code>.</p> <p>So that explains why generics aren't covariant. Let's look at the workaround:</p> <pre><code>Pair&lt;String, ? extends Future&lt;?&gt;&gt; pairOfStringAndSomethingThatIsAFutureOfSomething; </code></pre> <p>That variable name is a mouthful but I wanted it to describe exactly what's going on here. Before, the second type argument was <em>exactly</em> <code>Future&lt;?&gt;</code>. Now, we're saying that it's "some unknown type, which is or extends <code>Future&lt;?&gt;</code>. For example, it could be <code>Future&lt;?&gt;</code>, it could be <code>Future&lt;String&gt;</code>, it could even be <code>MySpecialFuture&lt;Integer&gt;</code>.</p> <p>We're voluntarily giving up some information about the type of this variable in order to relax what can be assigned to it. Now, this is legal:</p> <pre><code>pairOfStringAndSomethingThatIsAFutureOfSomething = pairOfStringAndFutureOfString; </code></pre> <p>The compiler protects against the earlier "heap pollution" scenario by preventing this unknown type from being "consumed":</p> <pre><code>//compiler error - nothing can be legally passed into setRight pairOfStringAndSomethingThatIsAFutureOfSomething.setRight(futureOfSomething); </code></pre> <p>To learn more about these retrictions, see this post: <a href="https://stackoverflow.com/questions/2723397/java-generics-what-is-pecs">What is PECS (Producer Extends Consumer Super)?</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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