Génériques et classe & lt ;? extends Enum & lt;? & gt ;, EnumSet.allOf (classe) vs class.getEnumConstants ()
J'ai le texte suivant BeanValidation code qui fonctionne très bien, et permet de valider qu'un haricot annoté avec:
@EnumValue(enumClass = MyTestEnum.class)
private String field;
public enum MyTestEnum {
VAL1, VAL2;
}
Sera validée uniquement si la valeur du champ est "VAL1" ou "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);
}
}
}
Ce que je ne comprends pas, c'est pourquoi ma première tentative a échoué. En utilisant à la place de la enumSelected.getEnumConstants()
ci-dessus le code suivant:
Set<? extends Enum<?>> enumInstances = EnumSet.allOf(enumSelected);
Intellij 12 ne met pas en évidence aucune erreur, mais le compilateur dit:
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<?>>
Je ne comprends pas le problème, et j'ai ce code qui fonctionne très bien:
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;
}
source d'informationauteur Sebastien Lorber
Vous devez vous connecter pour publier un commentaire.
Mon sentiment est que, dans
? extends Enum<?>
les deux?
pourraient être différents, alors queallOf
s'attend à unT extends Enum<T>
où les deuxT
sont les mêmes.Par exemple, considérons le code suivant:
Ces lignes de compilation:
parce que nous savons que les deux
T
dansenumValue.enumClass()
sont les mêmes, mais ce ne sera pas le cas:parce que vous avez perdu de l'information à l'aide d'un
Class<? extends Enum<?>>
comme une étape intermédiaire.Mon explication sur @assylias la solution:
Ce que nous voulons exprimer à propos du type de la classe, c'est que c'est un
mais Java ne permet pas d'introduire une variable de type
E
dans un corps de méthode.Généralement, nous pouvons exploiter générique et générique de capture d'introduire un type masqué variable
Mais cela ne fonctionne pas dans notre cas, depuis
T
dansClass<T>
ne dispose pas d'un bond qui le fait fonctionner.Donc nous avons besoin d'introduire un nouveau type avec le désiré lié
Nous appelons alors
EnumClass<E>.enumClass()
pour donner unqui est l'objectif que nous avons tenté de le faire.
Mais comment peut-on appeler le constructeur de
EnumClass
? L'origine du problème est que nous n'avons pas un type approprié pour lesenumClass
pourtant, le constructeur deEnumClass
veut correctement tapéenumClass
.Heureusement(?) la crue de type d'aide ici qui désactive les génériques de vérification de type
De sorte que le minimum de gymnastique nous avons besoin d'effectuer de jeter la classe pour le type désiré est