Интуитивно понятен ваш код;однако ограничение в системе типов Java делает его незаконным.Давайте сначала рассмотрим более простой пример
<T> void f1(List<T> a){ ... }
<T> void f2(List<T> a1, List<T> a2){ ... }
List<?> a = ...;
f1(a); // compiles
f2(a, a); // does not compile
При компиляции f1(a)
компилятор внутренне обрабатывает тип a
как List<X>
, где X - фиксированный, хотя и неизвестный тип.Это называется «захватом по шаблону».Передав List<X>
компилятору f1
, компилятор делает вывод, что T = X.
При компиляции f2(a,a)
происходит нечто подобное;однако подстановочный знак применяется к двум вхождениям a
по отдельности, в результате чего 1-й a
имеет тип List<X1>
, а 2-й a
- List<X2>
.Компилятор не анализирует, что a
остается неизменным, поэтому X1=X2
.Без этого знания передача List<X1>
и List<X2>
в f2()
не компилируется.
Обходной путь должен заставить a
появляться только один раз:
List<?> a = ...;
f2_1(a); // compiles
<T> void f2_1(List<T> a){ f2_2(a,a); } // compiles, two a's same type: List<T>
<T> void f2_2(List<T> a1, List<T> a2){ ... }
Назад к вашемуВ этом случае вам также понадобится вспомогательный метод:
<T, U> Form<U> createForm(Component<T, U> component, T object, String prefix)
{
return component.createForm(component.get(object), prefix + subPrefix);
}
--
Component<T, ?> component = e.getValue();
Form<?> form = createForm(component, object, prefix + subPrefix);
Для следующей задачи вам понадобится приведение.Нет другого способа сообщить компилятору, что компонент и форма имеют одинаковые значения U
.Это отношение не может быть выражено в системе типов Java, но оно гарантируется вашей логикой кода.Вы можете законно подавить предупреждение, потому что вы "проверили", чтобы убедиться, что приведение должно работать во время выполнения.