tags:

views:

307

answers:

2

The code below is throwaway, a failed idea to get an Enumeration to work in the new foreach loop, however I'd like to get it compiling since I keep running into an issue with generics and wild cards. For whatever reason I cannot see how to fix it.

So, what changes need to be made to make this compile?

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;


public class Main
{
    private ZipFile zipFile;

    public Set<String> entries()
    {
        final Set<String>                             names;
        final Enumeration<? extends ZipEntry>         enumeration;
        final IterableEnumeration<? extends ZipEntry> iteratable;

        names = new HashSet<String>();

        // zipFile.entries() returns "Enumeration<? extends ZipEntry>"
        enumeration = zipFile.entries();

        // this line won't compile
        iteratable  = new IterableEnumeration<? extends ZipEntry>(enumeration);

        for(final ZipEntry entry : iteratable)
        {
            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()
    {
        final EnumerationIterator<T> iterator;

        // yeah cannot do this since an Iterable is supposed to work multiple times on the same object and Enumeration is descructive...
        iterator = new EnumerationIterator<T>(enumeration);

        return (iterator);
    }
}

class EnumerationIterator<T>
    implements Iterator<T>
{
    private final Enumeration<T> enumeration;

    public EnumerationIterator(final Enumeration<T> e)
    {
        enumeration = e;
    }

    public boolean hasNext()
    {
        return (enumeration.hasMoreElements());
    }

    public T next()
    {
        return (enumeration.nextElement());
    }

    public void remove()
    {
        throw new UnsupportedOperationException("Cannt remove via an Enumeration");
    }
}

The error is:

Main.java:26: unexpected type
found   : ? extends java.util.zip.ZipEntry
required: class or interface without bounds
        iteratable  = new IterableEnumeration<? extends ZipEntry>(enumeration);
                                             ^
1 error
+2  A: 

This might help: http://www.javaspecialists.eu/archive/Issue107.html

jcrossley3
Thank you - the static "make" method is what I needed. Hopeully this solves my other problems with wildcards.
TofuBeer
+3  A: 

You cannot specify a wildcard when constructing a parameterized type. This is the correct syntax:

iteratable  = new IterableEnumeration<ZipEntry>(enumeration);

As you noted, there's difficulty in implementing Iterable with an Enumeration because Enumeration is one-time use, while code can rely on Iterable to create as many fresh Iterator objects as it wishes. You could safely use this in enhanced for-loops, but it would be unsafe to pass such an Iterable to any other method.


Oscar is right, the above change is not sufficient. I overlooked the fact that the underlying enumeration is "? extends ZipEntry". In addition, make the following changes:

class IterableEnumeration<T>
  implements Iterable<T>
{

  private final Enumeration<? extends T> enumeration;

  public IterableEnumeration(final Enumeration<? extends T> e)
  {
    enumeration = e;
  }

  ...

and

class EnumerationIterator<T>
  implements Iterator<T>
{

  private final Enumeration<? extends T> enumeration;

  public EnumerationIterator(final Enumeration<? extends T> e)
  {
    enumeration = e;
  }

  ...

These changes basically mean, "IterableEnumeration<T> can collaborate with an Enumeration of any sub-type of T."

erickson
I tried removing the ? in that code but doesn't work. What's the reason? The new message is: Cannot findconstructor IterableEnumeration(java.util.Enumeration<capture#125 of ? extends java.util.zip.ZipEntry>)
OscarRyz
I don't get it. Why is not possible to create such constructor?
OscarRyz
awn .. . a couple of hours late :) Thanks anyway!
OscarRyz
<? extends T> never thought of that one. Thanks. I had a brutal generic a couple of weeks ago - I wound up making it stretch over about 10 lines... I'll have to revisit it now.
TofuBeer