3

この質問では、TofuBeer は一般化された .xml の作成に問題がありましたIterableEnumeration

答えは、問題をほぼ解決したこのリンクhttp://www.javaspecialists.eu/archive/Issue107.htmlを指している jcrossley3 から来ました。

まだ一つ腑に落ちないことがあります。エリクソンが効果的に指摘したように、本当の問題は次のとおりです。

パラメーター化された型を構築するときにワイルドカードを指定することはできません

ただし、宣言でワイルドカードを削除しても機能しませんでした。

final IterableEnumeration<ZipEntry> iteratable 
                  = new IterableEnumeration<ZipEntry>(zipFile.entries());

次のエラーが発生します。

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

しかし、JavaSpecialist のサンプルは機能します。

  IterableEnumeration<String> ie =
              new IterableEnumeration<String>(sv.elements());

私が見つけることができる唯一の違いは、JavaSpecialists ブログでは、署名が次Enumerationの から来ていることです。Vector

public Enumeration<E> elements()

失敗したものはZipFile、署名が次のとおりです。

public Enumeration<? extends ZipEntry> entries()

最後に、これはすべて for-each コンストラクトとリンクで提案されている static make メソッドによって吸収されます

for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() ))  {
    if(!(entry.isDirectory())) {
        names.add(entry.getName());
    }
}

しかし!!そのニュースレターのポイントは、この問題を解決することではなく、ジェネリック型を指定する必要性を回避することでした。構文が見苦しいからです!!

だから..私の質問は:

何が起こっている?

IterableEnumerationパラメータEnumerationの型が である場合、なぜインスタンスを作成しないの<? extends SomeClass>ですか そして、make for-each 構造が問題を飲み込むのはなぜですか?!!!

なぜこれが機能するのですか:

for(final ZipEntry entry : IterableEnumeration.make( zipFile.entries() ))  {

しかし、これはうまくいきませんか?

final IterableEnumeration<ZipEntry> iteratable
                     = IterableEnumeration.make( zipFile.entries() );

以下は、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);
    }
}

理解したい!!

4

2 に答える 2

3

foreach ループで何が起こっているのかわかりませんが、ZipFile.entries() から返される未指定の型を受け入れるには、IterableEnumeration の宣言にワイルドカードを追加する必要があります。

交換

    private final Enumeration<T> enumeration;

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

    public static <T> Iterable<T> make(Enumeration<T> en) {
        return new IterableEnumeration<T>(en);
    }

    private final Enumeration<? extends T> enumeration;

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

    public static <T> Iterable<T> make(Enumeration<? extends T> en) {
        return new IterableEnumeration<T>(en);
    }
于 2009-03-07T02:47:14.163 に答える
0

ここでの根本的な問題は、ジェネリックをサポートするようにZipFileentries()が変更されたときに、メンテナがメソッドの戻り型を作成することを選択したことEnumeration<? extends ZipEntry>です(おそらく、サブクラスのメソッド JarFileが返すことができるようにEnumeration<JarEntry>)。これはあなたが見ている問題を引き起こします。

は共変的に使用されるためEnumeration<T>(常にそうであるように、値を返すだけです)、常にメソッド引数にをとらせる必要がありますEnumeration<? extends T>

于 2009-08-04T18:50:12.080 に答える