2014-12-31 9 views
5

次のコードコンパイル(期待通りのテストを実行する):乖離 - 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()に使用することができる方法のPARAMとしてクラスを取り、またところでEnumSet

に列挙オブジェクトのタイプを決定することこの方法の目的を批判しないでください。私はより有用/有意義なコードからそれを減らしました。私は "enum型から最初の要素を見つける"というメリットについて議論するのは興味がありません - それはこの質問のポイントではありません。

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

また、あなたはEnumSetでワイルドカードを必要とし、あなたはありません:あなたはTが列挙型である、またはそれはEnumSetの制約を満たしていないことを確認する必要があり

+0

これはjavac(JDK 1.7.0_60)のバグであるようです。以下の回答は回避策です(実際にはより洗練されたコード)。詳細な解析はhttps://bugs.eclipse.org/bugs/show_bug.cgi?id=456459#c7 –

答えて

4

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

のような型パラメータを宣言するときに '&'演算子を適用することはできませんでした。 Javaコードを書くのに18年近く経っても、私は今日何か新しいことを学びました! –

+0

ところで、私が 'Class'の生の形式を使用したのは、Eclipseコンパイラが' Class'型パラメータの値を受け入れない 'Tum'を拡張していないからです。だからrawを使うことは、 'Cloneable'と' Enum'を 'T'に組み合わせることを知らないという副作用でした。 –

+0

興味深いことに、Eclipseは 'EnumSet 'としてセットを宣言することはできません。*「バインドされた不一致:タイプTは、EnumSet タイプの制限付きパラメータ> *。幸いにも、 'EnumSet <? T? 'は機能し、等価です。 –

関連する問題