I've been banging my head on the table over this for a few hours now.
I have this Map:
private static Map<Class<? extends BaseClass>, Predicate<? extends BaseClass>> constraints;
And I have this method:
public static <C extends BaseClass> Predicate<C> getConstraints(Class<? super C> clazz) {
if (clazz == BaseClass.class) {
return (Predicate<C>) constraints.getOrDefault(BaseClass.class, x -> true);
}
Class<? super C> superClass = clazz.getSuperclass();
return constraints.getOrDefault(clazz, x -> true).and(getConstraints(superClass));
}
All this is supposed to do is to chain all constraints for a certain class (and the superclasses) in a Predicate<T>
using the and()
method.
The generics seem logical to me but I still get an error when making the recursive call. getConstraints(Class<? super C>) cannot be applied to Class<capture of ? super E>
. I don't get it because superClass
is of the type Class<? super C>
which is exactly the parameter that my method accepts. Any ideas?
You could use a type variable that represents the superclass:
@SuppressWarnings("unchecked")
public static <S extends BaseClass, C extends S> Predicate<C> getConstraints(Class<C> clazz) {
if (clazz == BaseClass.class) {
return (Predicate<C>) constraints.getOrDefault(BaseClass.class, x -> true);
}
Class<S> superClass = (Class<S>) clazz.getSuperclass();
Predicate<C> p1 = (Predicate<C>) constraints.getOrDefault(clazz, x -> true);
Predicate<S> p2 = getConstraints(superClass);
return p1.and(p2);
}
You will also have to cast the result of getOrDefault
, since putting the Predicate
in the map 'forgets' the type information, and you get back a generic Predicate<? extends BaseClass>
, which you can't use directly.