Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do I fix this Java generics wildcard error?
    text
    copied!<p>In this <a href="https://stackoverflow.com/questions/620934/wildcards-and-generics-error">question</a>, TofuBeer was having problems creating a genericized <code>IterableEnumeration</code>.</p> <p>The answer came from jcrossley3 pointing to this link <a href="http://www.javaspecialists.eu/archive/Issue107.html" rel="nofollow noreferrer">http://www.javaspecialists.eu/archive/Issue107.html</a> which pretty much solved the problem. </p> <p>There is still one thing I don't get. The real problem, as effectively pointed out by erickson, was that:</p> <blockquote> <p><em>You cannot specify a wildcard when constructing a parameterized type</em></p> </blockquote> <p>But removing the wildcard in the declaration didn't work either:</p> <pre><code>final IterableEnumeration&lt;ZipEntry&gt; iteratable = new IterableEnumeration&lt;ZipEntry&gt;(zipFile.entries()); </code></pre> <p>Results in the following error: </p> <pre><code>Main.java:19: cannot find symbol symbol : constructor IterableEnumeration(java.util.Enumeration&lt;capture#469 of ? extends java.util.zip.ZipEntry&gt;) location: class IterableEnumeration&lt;java.util.zip.ZipEntry&gt; final IterableEnumeration&lt;ZipEntry&gt; iteratable = new IterableEnumeration&lt;ZipEntry&gt;( zipFile.entries()); ^ 1 error </code></pre> <p>But the samples in the JavaSpecialist do work:</p> <pre><code> IterableEnumeration&lt;String&gt; ie = new IterableEnumeration&lt;String&gt;(sv.elements()); </code></pre> <p>The only difference I can spot is that in the JavaSpecialists blog, the <code>Enumeration</code> comes from a <code>Vector</code> whose signature is: </p> <pre><code>public Enumeration&lt;E&gt; elements() </code></pre> <p>while the one that fails comes from <code>ZipFile</code> whose signature is:</p> <pre><code>public Enumeration&lt;? extends ZipEntry&gt; entries() </code></pre> <p>Finally, all of this is absorbed by the for-each construct and the static make method suggested in the link</p> <pre><code>for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() )) { if(!(entry.isDirectory())) { names.add(entry.getName()); } } </code></pre> <p>But!! the point in that newsletter was not to solve this problem, but to avoid the need to specify a generic type, just because the syntax looks ugly!!</p> <p>So.. my questions is:</p> <h1>What is happening?</h1> <p>Why doesn't creating an instance of <code>IterableEnumeration</code> work when the parameter is an <code>Enumeration</code> whose type is <code>&lt;? extends SomeClass&gt;</code> ? And why does the make for-each construct swallow the problem?!!!</p> <p>Why does this work:</p> <pre><code>for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() )) { </code></pre> <p>but this not work?</p> <pre><code>final IterableEnumeration&lt;ZipEntry&gt; iteratable = IterableEnumeration.make( zipFile.entries() ); </code></pre> <p>Below is a (slightly) modified version of TofuBeer's original code:</p> <pre><code>import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.Vector; public class Main { private ZipFile zipFile; public Set&lt;String&gt; entries() { final Vector&lt;ZipEntry&gt; vector = new Vector&lt;ZipEntry&gt;(); // why this works. //final IterableEnumeration&lt;ZipEntry&gt; iteratable = new IterableEnumeration&lt;ZipEntry&gt;( vector.elements() ); // but this do not. //final IterableEnumeration&lt;ZipEntry&gt; iteratable = new IterableEnumeration&lt;ZipEntry&gt;( zipFile.entries() ); // nor this final IterableEnumeration&lt;ZipEntry&gt; iteratable = IterableEnumeration.make( zipFile.entries() ); // And what's with the for-each that doesn't care about the type? final Set&lt;String&gt; names = new HashSet&lt;String&gt;(); for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() )) { if(!(entry.isDirectory())) { names.add(entry.getName()); } } return (names); } } class IterableEnumeration&lt;T&gt; implements Iterable&lt;T&gt; { private final Enumeration&lt;T&gt; enumeration; public IterableEnumeration(final Enumeration&lt;T&gt; e) { enumeration = e; } public Iterator&lt;T&gt; iterator() { return new Iterator&lt;T&gt;() { public boolean hasNext() { return (enumeration.hasMoreElements()); } public T next() { return (enumeration.nextElement()); } public void remove() { throw new UnsupportedOperationException("Cannot remove via an Enumeration"); } }; } // As suggested by http://www.javaspecialists.eu/archive/Issue107.html // but doesn't help with: final IterableEnumeration&lt;ZipEntry&gt; iteratable = IterableEnumeration.make( zipFile.entries() ); public static &lt;T&gt; Iterable&lt;T&gt; make(Enumeration&lt;T&gt; en) { return new IterableEnumeration&lt;T&gt;(en); } } </code></pre> <p>I want to understand it!!</p>
 

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