如何使用Map调用对象上的操作

时间:2017-03-26 21:48:23

标签: java

我想在通用代码段中调用特定的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

我明白为什么失败了。但是,有没有一种优雅的方法可以在不诉诸案例陈述的情况下做到这一点?

1 个答案:

答案 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());