2013-03-12 93 views
10

我有正常工作,並允許以下BeanValidation代碼來驗證帶註釋一個bean:泛型和類<?擴展Enum <?>>,EnumSet.allOf(類)與class.getEnumConstants()

@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); 
    } 
    } 

} 

我不明白的是爲什麼我的第一次嘗試失敗。使用替代enumSelected.getEnumConstants()以下代碼上面:

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

的IntelliJ 12不突出任何錯誤,但是編譯器說:

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 – 2013-03-12 16:38:31

+0

這一個太:http://stackoverflow.com/questions/3546745/multiple-wildcards-on-一個泛型米ethods-makes-java-compiler-and-me-very-confu – assylias 2013-03-12 16:39:41

+1

@ChristopheRoussy:Ticket?現在StackOverflow是一個支持系統:) – mellamokb 2013-03-12 16:52:32

回答

8

我的猜測是,在? extends Enum<?>的兩個?可能不同,而allOf預計T 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()兩個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 > – 2013-03-13 08:44:28

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) 

但是,這不會影響我們的情況下工作,因爲TClass<T>沒有了界限,使得它的工作。

因此,我們需要與期望勢必

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<E>.enumClass()以產生

Class<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很好的解釋。我想知道'EnumClass wild = new EnumClass <>(enumClass);'在Java 7中有效。 – 2013-07-20 17:21:36

相關問題