6

次のコードは、Eclipse でコンパイル (および期待どおりにテストを実行) します。

import java.util.EnumSet;
public class EnumTest {

    static enum Cloneables implements Cloneable {
        One, Two, Three;
    }

    public <T extends Cloneable> T getOne(Class enumType) {
        EnumSet<? extends T> set = EnumSet.allOf(enumType);
        return set.iterator().next();
    }
}

ただし、javac直接 (JDK 7) または Maven 経由でコンパイルすると、次のエラーで失敗します。

type argument ? extends T is not within bounds of type-variable E

正直なところ、列挙型 + インターフェース + 型パラメーター (ジェネリック) の複雑さが一気に複雑になり、コードを書いているときに気が遠くなりましたが、ようやく正しく理解できたと思いました。

目標は、次のような呼び出しコードを記述することです。

Cloneable something = enumTest.getOne(Cloneables.class);

たとえば、Eclipse では、次のテストがコンパイルされ、パスします。

@Test
public void testGetFirst() {
    assertSame(Cloneables.One, getOne(Cloneables.class));
}

Eclipse と javac のどちらが「正しい」かについての手がかりをいただければ幸いです。

また、アイデアを実装するための代替方法についてのアドバイスも高く評価されます。クラスを、で使用できEnumSet.allOf()、Enum オブジェクトのタイプを決定するメソッド param として使用します。EnumSet

ところで、このメソッドの目的をわざわざ批判しないでください。より便利で意味のあるコードから減らしました。「列挙型から最初の要素を見つける」ことのメリットについて議論することに興味はありません-それはこの質問のポイントではありません。

4

1 に答える 1

3

が列挙型であることを確認する必要があります。そうしないと、次Tの制約を満たしませんEnumSet

public <T extends Enum<T> & Cloneable> T getOne(Class enumType) 

また、 にワイルドカードは必要ありませんEnumSet。生のClass型は使用しないでください。

public <T extends Enum<T> & Cloneable> T getOne(Class<T> enumType) {
    EnumSet<T> set = EnumSet.allOf(enumType);
    return set.iterator().next();
}
于 2014-12-31T22:45:34.173 に答える