Using Java wildcards

徘徊边缘 提交于 2019-12-05 16:13:16

Intuitively your code makes perfect sense; however a limitation in Java type system makes it illegal. Let's see a simpler example first

<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

When compiling f1(a), compiler internally treats the type of a as List<X>, where X is a fixed albeit unknown type. This is called "wildcard capture". Passing a List<X> to f1 compiles, compiler infers that T=X.

When compiling f2(a,a), similar thing happens; however, wildcard capture is applied on two occurrences of a seperately, resulting the 1st a being of type List<X1>, and the 2nd a of List<X2>. Compiler doesn't not analyze that a remain unchanged therefore X1=X2. Without that knowledge, passing List<X1> and List<X2> to f2() does not compile.

The workaround is to make a appear only once:

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){ ... }

Back to your case, you need a helper method too:

<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);

For the next problem, you need a cast. There is no other way to tell compiler that the component and the form share the same U. That relation cannot be expressed in Java type system, but it is guaranteed by your code logic. You can legitimately suppress the warning, because you have "checked" to make sure that the cast must work at runtime.

Have a look at the Composite Pattern. Then, if you think using generics is useful for your problem, go and read a good tutorial such as this one.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!