In diesem question hatte TofuBeer Probleme mit der Erstellung eines generischen IterableEnumeration
.
Die Antwort kam von jcrossley3, der auf diesen Link verwies http://www.javaspecialists.eu/archive/Issue107.html Damit war das Problem so gut wie gelöst.
Eine Sache verstehe ich immer noch nicht. Das eigentliche Problem war, wie von erickson treffend dargelegt, dass:
Bei der Konstruktion eines parametrisierten Typs können Sie keinen Platzhalter angeben
Aber auch das Entfernen des Platzhalters in der Deklaration hat nicht funktioniert:
final IterableEnumeration<ZipEntry> iteratable
= new IterableEnumeration<ZipEntry>(zipFile.entries());
Dies führt zu dem folgenden Fehler:
Main.java:19: cannot find symbol
symbol : constructor IterableEnumeration(java.util.Enumeration<capture#469 of ? extends java.util.zip.ZipEntry>)
location: class IterableEnumeration<java.util.zip.ZipEntry>
final IterableEnumeration<ZipEntry> iteratable = new IterableEnumeration<ZipEntry>( zipFile.entries());
^
1 error
Aber die Beispiele im JavaSpecialist funktionieren:
IterableEnumeration<String> ie =
new IterableEnumeration<String>(sv.elements());
Der einzige Unterschied, den ich feststellen kann, ist, dass im JavaSpecialists-Blog die Enumeration
kommt von einer Vector
dessen Unterschrift lautet:
public Enumeration<E> elements()
während derjenige, der scheitert, von ZipFile
dessen Unterschrift lautet:
public Enumeration<? extends ZipEntry> entries()
Schließlich wird all dies durch das for-each-Konstrukt und die statische make-Methode absorbiert, die in dem Link
for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() )) {
if(!(entry.isDirectory())) {
names.add(entry.getName());
}
}
Aber in diesem Rundschreiben ging es nicht darum, dieses Problem zu lösen, sondern zu vermeiden, dass ein allgemeiner Typ angegeben werden muss, nur weil die Syntax hässlich aussieht!!!
Meine Frage ist also:
Was geschieht hier?
Warum funktioniert die Erstellung einer Instanz von IterableEnumeration
funktionieren, wenn der Parameter ein Enumeration
deren Typ ist <? extends SomeClass>
? Und warum schluckt das Fabrikat für jedes Konstrukt das Problem?!!!
Warum funktioniert das?
for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() )) {
aber das funktioniert nicht?
final IterableEnumeration<ZipEntry> iteratable
= IterableEnumeration.make( zipFile.entries() );
Nachfolgend finden Sie eine (leicht) modifizierte Version des ursprünglichen Codes von TofuBeer:
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<String> entries() {
final Vector<ZipEntry> vector = new Vector<ZipEntry>();
// why this works.
//final IterableEnumeration<ZipEntry> iteratable = new IterableEnumeration<ZipEntry>( vector.elements() );
// but this do not.
//final IterableEnumeration<ZipEntry> iteratable = new IterableEnumeration<ZipEntry>( zipFile.entries() );
// nor this
final IterableEnumeration<ZipEntry> iteratable = IterableEnumeration.make( zipFile.entries() );
// And what's with the for-each that doesn't care about the type?
final Set<String> names = new HashSet<String>();
for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() )) {
if(!(entry.isDirectory())) {
names.add(entry.getName());
}
}
return (names);
}
}
class IterableEnumeration<T> implements Iterable<T> {
private final Enumeration<T> enumeration;
public IterableEnumeration(final Enumeration<T> e) {
enumeration = e;
}
public Iterator<T> iterator() {
return new Iterator<T>() {
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<ZipEntry> iteratable = IterableEnumeration.make( zipFile.entries() );
public static <T> Iterable<T> make(Enumeration<T> en) {
return new IterableEnumeration<T>(en);
}
}
Ich will es verstehen!!