2013-03-12 16 views
10

I正常に動作し、許可次BeanValidationコードが注釈付きでBeanがあることを検証する必要があります:ジェネリックとクラス<?列挙型<?>>、class.getEnumConstants対EnumSet.allOf(クラス)()拡張

@EnumValue(enumClass = MyTestEnum.class) 
    private String field; 

    public enum MyTestEnum { 
    VAL1, VAL2; 
    } 

のみ検証されますフィールド値が「VAL1」または「VAL2」の場合

public class EnumNameValidator implements ConstraintValidator<EnumValue, String> { 

    private Set<String> AVAILABLE_ENUM_NAMES; 

    @Override 
    public void initialize(EnumValue enumValue) { 
    Class<? extends Enum<?>> enumSelected = enumValue.enumClass(); 
    Set<? extends Enum<?>> enumInstances = Sets.newHashSet(enumSelected.getEnumConstants()); 
    AVAILABLE_ENUM_NAMES = FluentIterable 
      .from(enumInstances) 
      .transform(PrimitiveGuavaFunctions.ENUM_TO_NAME) 
      .toImmutableSet(); 
    } 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
    if (value == null) { 
     return true; 
    } else { 
     return AVAILABLE_ENUM_NAMES.contains(value); 
    } 
    } 

} 

最初の試みが失敗した理由はわかりません。すべてのエラーを強調表示しません

Set<? extends Enum<?>> enumInstances = EnumSet.allOf(enumSelected); 

のIntelliJ 12が、コンパイラは言う:次のコードの上にenumSelected.getEnumConstants()の代わりに使用して

java: method allOf in class java.util.EnumSet<E> cannot be applied to given types; 
    required: java.lang.Class<E> 
    found: java.lang.Class<capture#1 of ? extends java.lang.Enum<?>> 
    reason: inferred type does not conform to declared bound(s) 
    inferred: capture#1 of ? extends java.lang.Enum<?> 
    bound(s): java.lang.Enum<capture#1 of ? extends java.lang.Enum<?>> 

私は問題を理解していない、と私はまた、正常に動作しているコードを持っている:

private static <T extends Enum<T> & EnumAlternativeName> T safeGetByAlternativeName(Class<T> enumClass, String alternativeName) { 
    for (T t : EnumSet.allOf(enumClass)) { 
     if (t.getAlternativeName().equals(alternativeName)) { 
     return t; 
     } 
    } 
    return null; 
    } 
+0

関連チケット:http://stackoverflow.com/questions/5548091/problem-when-trying-to-use-generics –

+0

これも1つです:http://stackoverflow.com/questions/3546745/multiple-wildcards-on- α-ジェネリック-mコンパイルと私の非常にconfuを作る – assylias

+1

@ChristopheRoussy:チケット?今はStackOverflowをサポートしていますか? – mellamokb

答えて

8

私の推測であることを? extends Enum<?>で2つの?は異なる可能性がありますが、allOfT extends Enum<T>を期待していますが、両方ともTが同じです。これらの行は、コンパイルされます

static enum MyEnum {} 
static class EnumValue<T extends Enum<T>> { 
    Class<T> enumClass; 
    EnumValue(Class<T> enumClass) { 
     this.enumClass = enumClass; 
    } 
    Class<T> enumClass() { return enumClass; } 
} 

EnumValue<?> enumValue = new EnumValue(MyEnum.class); // raw constructor 
Set<? extends Enum<?>> enumInstances = EnumSet.allOf(enumValue.enumClass()); 

を我々はenumValue.enumClass()で2 Tが同じであるが、これがないことを知っているので:

次のコードを考えてみたとえば

EnumValue enumValue = new EnumValue(MyEnum.class); 
Class<? extends Enum<?>> enumSelected = enumValue.enumClass(); 
Set<? extends Enum<?>> enumInstances = EnumSet.allOf(enumSelected); 

中間ステップとしてClass<? extends Enum<?>>を使用する。

+0

ありがとう、私は、EnumValue > –

3

@のassyliasのソリューションで私の説明:

私たちはクラスの種類についての表現したいこと、それは

Class<E>, for some E, that E <: Enum<E> 

だが、Javaは、私たちは、変数Eでタイプを導入することはできませんということですメソッド本体。

通常、我々は

class G<T extends b(T)> { ... } // b(T) is a type expression that may contain T 

G<? extends A> --capture--> G<T>, for some T, that T <: A & b(T) 

変数隠しタイプを導入するために、ワイルドカードとワイルドカードのキャプチャを利用することができます。しかしClass<T>Tはそれを動作させ、その境界を持っていないので、これは、私たちのケースでは動作しません。

だから我々は希望我々は、我々が達成しようとしてきた目標である

Class<E>, for some E, that E <: Enum<E> 

を得EnumClass<E>.enumClass()を呼び出し

class EnumClass<E extends Enum<E>> // called EnumValue in assylias's solution 

    EnumClass(Class<E> enumClass) 

    Class<E> enumClass() 

EnumClass<?> --capture--> EnumClass<E>, for some E, that E <: Enum<E> 

を拘束した新しいタイプを導入する必要があります。

しかし、どのようにしてEnumClassのコンストラクタを呼び出すことができますか?この問題の原因は、enumClassの適切な型がないことです。さらに、EnumClassのコンストラクタでは、適切に型指定されたenumClassが必要です。

Class<not-proper> enumClass = ...; 
new EnumClass<...>(enumClass); // wont work 

は幸い(?)の生タイプは、ジェネリック医薬品が

EnumClass raw = new EnumClass(enumClass); // no generics 
EnumClass<?> wild = raw; 

だから我々は必要なタイプにクラスをキャストするために実行する必要がある最小の体操が

((EnumClass<?>)new EnumClass(enumClass)).enumClass() 
される型チェック無効にするここに役立ちます
+0

+1というアノテーションのenum属性を作ることができないため、選択肢がないと思います。 'EnumClass wild = new EnumClass <>(enumClass);'がJava 7で動作するかどうか疑問に思っています。 –

関連する問題