Уйти от ошибки компиляции: reason: Incompatible equality constraint: T and?
В приложении есть интерфейс обработчик с обобщенным типом (в теории - любой тип):
public interface Worker<T> {
T action1();
void action2(T object);
}
примеры реализации:
public class Worker1 implements Worker<String> {
@Override
public String action1() {
return "1";
}
@Override
public void action2(String object) {
System.out.println("String: " + object.replace("1", "2"));
}
}
public class Worker2 implements Worker<Integer> {
@Override
public Integer action1() {
return 1;
}
@Override
public void action2(Integer object) {
System.out.println("Integer: " + (object + 1));
}
}
а так же есть сервис, который может вызывать эти обработчики:
public class Runner {
<T> void run(List<Worker<T>> workers) {
for (Worker<T> worker : workers) {
T object = worker.action1();
worker.action2(object);
}
}
}
Вызов сервиса выглядит следующим образом:
List<Worker<?>> workers = Lists.newArrayList(new Worker1(), new Worker2());
new Runner().run(workers);
На строке:
new Runner().run(workers);
будет ошибка компиляции:
reason: Incompatible equality constraint: T and ?
что логично, т.к. в данном случае нужно определять коллекцию Worker не с wildcard, а с конкретным типом (java не может вывести тип).
Вопрос, каким образом можно переделать данный алгоритм, для того, чтобы:
- Сохранить типизацию в Worker, для того, чтобы в параметрах метода action2 можно было работать с конкретным типом без приведения типов (cast).
- Инициализировать список Worker'ов разного типа и передать их в сервис Runner без ошибок и без предупреждений вида: raw use parametrized.. (то есть не использовать raw типы).
Подходил к проблеме с разных сторон (шаблоны проектирования, изменение архитектуры и так далее), но пока решение не удалось найти, надеюсь на помощь сообщества.
Заранее спасибо.