Note that there are some explanatory texts on larger screens.

plurals
  1. POWhen do Java generics require <? extends T> instead of <T> and is there any downside of switching?
    primarykey
    data
    text
    <p>Given the following example (using JUnit with Hamcrest matchers):</p> <pre><code>Map&lt;String, Class&lt;? extends Serializable&gt;&gt; expected = null; Map&lt;String, Class&lt;java.util.Date&gt;&gt; result = null; assertThat(result, is(expected)); </code></pre> <p>This does not compile with the JUnit <code>assertThat</code> method signature of:</p> <pre><code>public static &lt;T&gt; void assertThat(T actual, Matcher&lt;T&gt; matcher) </code></pre> <p>The compiler error message is:</p> <pre><code>Error:Error:line (102)cannot find symbol method assertThat(java.util.Map&lt;java.lang.String,java.lang.Class&lt;java.util.Date&gt;&gt;, org.hamcrest.Matcher&lt;java.util.Map&lt;java.lang.String,java.lang.Class &lt;? extends java.io.Serializable&gt;&gt;&gt;) </code></pre> <p>However, if I change the <code>assertThat</code> method signature to:</p> <pre><code>public static &lt;T&gt; void assertThat(T result, Matcher&lt;? extends T&gt; matcher) </code></pre> <p>Then the compilation works.</p> <p>So three questions:</p> <ol> <li>Why exactly doesn't the current version compile? Although I vaguely understand the covariance issues here, I certainly couldn't explain it if I had to.</li> <li>Is there any downside in changing the <code>assertThat</code> method to <code>Matcher&lt;? extends T&gt;</code>? Are there other cases that would break if you did that?</li> <li>Is there any point to the genericizing of the <code>assertThat</code> method in JUnit? The <code>Matcher</code> class doesn't seem to require it, since JUnit calls the matches method, which is not typed with any generic, and just looks like an attempt to force a type safety which doesn't do anything, as the <code>Matcher</code> will just not in fact match, and the test will fail regardless. No unsafe operations involved (or so it seems).</li> </ol> <p>For reference, here is the JUnit implementation of <code>assertThat</code>:</p> <pre><code>public static &lt;T&gt; void assertThat(T actual, Matcher&lt;T&gt; matcher) { assertThat("", actual, matcher); } public static &lt;T&gt; void assertThat(String reason, T actual, Matcher&lt;T&gt; matcher) { if (!matcher.matches(actual)) { Description description = new StringDescription(); description.appendText(reason); description.appendText("\nExpected: "); matcher.describeTo(description); description .appendText("\n got: ") .appendValue(actual) .appendText("\n"); throw new java.lang.AssertionError(description.toString()); } } </code></pre>
    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.
 

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