I have a more complicated issue (than question 'Java map with values limited by key's type parameter' question) for mapping key and value type in a Map. Here it is:
interface AnnotatedFieldValidator<A extends Annotation> {
void validate(Field f, A annotation, Object target);
Class<A> getSupportedAnnotationClass();
}
Now, I want to store validators in a map, so that I can write the following method:
validate(Object o) {
Field[] fields = getAllFields(o.getClass());
for (Field field: fields) {
for (Annotation a: field.getAnnotations()) {
AnnotatedFieldValidator validator = validators.get(a);
if (validator != null) {
validator.validate(field, a, target);
}
}
}
}
(type parameters are omitted here, since I do not have the solution). I also want to be able to register my validators:
public void addValidator(AnnotatedFieldValidator<? extends Annotation> v) {
validators.put(v.getSupportedAnnotatedClass(), v);
}
With this (only) public modifier method, I can ensure the map contains entries for which the key (annotation class) matches the validator's supported annotation class.
Here is a try:
I declare the validators Map like this:
private Map<Class<? extends Annotation>, AnnotatedFieldValidator<? extends Annotation>> validators;
I'm aware I cannot properly link the key and value (link is assumed OK due to only access through addValidator()
), so I tried a cast:
for (Annotation a: field.getAnnotations()) {
AnnotatedFieldValidator<? extends Annotation> validator = validators.get(a);
if (validator != null) {
validator.validate(field, validator.getSupportedAnnotationClass().cast(a), target);
}
}
But this does not work: The method validate(Field, capture#8-of ?, Object) in the type AnnotatedFieldValidator<capture#8-of ?> is not applicable for the arguments (Field, capture#9-of ?, Object)
.
I can't figure out why this does not work: the AnnotatedFieldValidator
has a single type parameter (A), which is used both as the return type of getSupportedAnnotationClass()
and as a parameter of validate()
; thus, when casting the annotation to supportedAnnotationClass, I should be able to pass it as the parameter to validate()
. Why is the result of getSupportedAnnotationClass()
considered a different type than the parameter of validate()
?
I can solve the validate()
method by removing wildcards in the validators declaration and validate()
method, but then, of course, addValidator()
doesn't compile.