我想在通用代码段中调用特定的setter。当然,我可以诉诸案例陈述,但它会变大,所以我更喜欢Map。
这是我到目前为止所提出的:
public class Tester {
private static final Map<String, Setter<Target, ?>> MY_SETTERS = new HashMap<>();
static {
MY_SETTERS.put("SOURCE1", ( Target t, Source1 s ) -> t.setSource1( s ) );
MY_SETTERS.put("SOURCE2", ( Target t, Source2 s ) -> t.setSource2( s ) );
}
@FunctionalInterface
private interface Setter<T, S> {
void set( T target, S source );
}
public static void main( String[] args ) {
Target t = new Target();
MY_SETTERS.get( "SOURCE1" ).set( t, new Source1() );
}}
但是,这给了我一个&#34;不兼容的类型:Source1无法转换为CAP#1 其中CAP#1是一个新的类型变量: CAP#1从捕获?&#34;
扩展了Object我明白为什么失败了。但是,有没有一种优雅的方法可以在不诉诸案例陈述的情况下做到这一点?
答案 0 :(得分:1)
由于地图中的通配符类型,您必须在某处绘制一条线。这有点难看,但我有时会这样做:
定义一个通用辅助方法,将Setter
强制转换为您所请求的类型:
public static <T, S> Setter<T, S> getSetter(String id) {
return (Setter<T, S>) MY_SETTERS.get(id);
}
像这样检索并调用setter:
getSetter("SOURCE1").set(t, new Source1());
Java将从传递的参数中推断出类型参数,并且调用本身看起来很好。由于未经检查的演员表,您将收到编译器的投诉。
显然,你必须绝对确定你所要求的是你所期望的,否则你将获得ClassCastException
。例如。执行以下操作将产生所述异常,因为您检索Source1
的setter但使用Source2
调用它:
getSetter("SOURCE1").set(t, new Source2());