2013-03-12 62 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

相关问题