Вы пытаетесь использовать дженерики во время выполнения. Если вы не знаете во время компиляции типы, которые вам нужно обрабатывать (будь то реальный тип или сам параметр типа), вы не можете использовать общие, простые и понятные. Это только конструкция времени компиляции (или в основном).
Здесь вы пытаетесь обрабатывать вещи как обобщенно, так и динамически. Это вообще невозможно. Используйте сырые типы и живите с типом unsafety.
Я бы сказал, что вы просто напрашиваетесь на неприятности с этим:
abstract class RuleHandler<T extends Rule>
{
abstract void doStuff(T rule);
}
Просто сделай так:
abstract class RuleHandler
{
abstract void doStuff(Rule rule);
}
И затем регистрировать этот обработчик правил только для тех типов, которые он может обработать.
Редактировать
Исходя из вашего комментария, кажется, что ваша цель состоит в том, чтобы навязать ваш дизайн пользователям вашего интерфейса. Я поддерживаю аргумент, что вы должны отделить концепцию фильтрации и обработки.
Тем не менее, другой вариант - оставить маркер класса вне самого обработчика и сгенерировать ваш метод регистра.
interface RuleHandler<T extends Rule> {
void doStuff(T rule);
}
//...
public <T> void register(Class<T> type, RuleHandler<? super T> handler) {
map.put(type, handler);
}
public void process() {
for ( Rule r : rules ) {
for(Map.Entry<Class<?>, RuleHandler<?>> entry : map.entrySet() ) {
if ( entry.getKey().instanceOf(r) ) {
@SuppressWarnings("unchecked")
((RuleHandler)entry.getValue()).doStuff(r);
}
}
}
}
Здесь мы подавляем предупреждение при использовании необработанного типа RuleHandler. Мы знаем, что это безопасно только через проверку, просматривая доступ к map
и видя, что класс всегда соответствует параметру типа RuleHandler
. Однако это, очевидно, будет безопасно только в том случае, если для клиента не было предупреждений о безопасности типов, когда они вызывали register()
(то есть они параметризовали вызов register()
).
(внутренний цикл for был добавлен поверх get
, так что для подклассов данного подкласса правила будет найден обработчик)