实现与类类型相关的if语句的更有效方法

时间:2017-12-06 17:57:20

标签: java

目前我有一个元组的ArrayDeque,如下所示(我认为这里有一个类可能有帮助),目前已经过序列化并通过网络发送:

private ArrayDeque<Triple<Integer, Object, Class>> paramList = new ArrayDeque<>();

元组中的对象类型可以是原始的,例如int,bool或真实类,例如Date,time(没有一个是我的实现)。

现在我正在遍历列表并根据它的类类型调用方法,显然这会变得繁琐的修改和更新。 例如(st是PreparedStatement):

for (Triple<Integer, Object, Class> param : paramList) {
    if(param.getMiddle() instanceof String){
        st.setString(parm.getLeft(),param.getMiddle());
    }else if(param.getMiddle() instanceof Integer){
        st.setInt(parm.getLeft(),param.getMiddle());
    } //... more class type checks doing the same thing
}

我遇到了这篇https://stackoverflow.com/a/5579385/5858208帖子,但由于这不是我实施的课程,所以我做不了多少。

所以我的问题是,是否有一种更有效和可维护的方式来实现这个想法,因为我在元组对象中确切地说它是什么类?

1 个答案:

答案 0 :(得分:0)

您可以创建一个Map,其中包含代码支持的所有类的键,以及作为调用正确setter的lambda表达式的值。

这些方面的东西:

@FunctionalInterface
interface PSConsumer<T,U> {
    void accept(T t, U u) throws SQLException;
}

private Map<Class<?>, PSConsumer<PreparedStatement, Triple<Integer, Object, Class<?>>>> setters = new HashMap<>();
{
    setters.put(String.class, (st, param) -> st.setString(param.getLeft(), (String) param.getMiddle()));
    setters.put(Integer.class, (st, param) -> st.setInt(param.getLeft(), (Integer) param.getMiddle()));
    // add here code for all the classes that you support
}

for (Triple<Integer, Object, Class<?>> param : paramList) {
    // this will throw an NPE if param.getMiddle() returns null or it's class is not in the map:
    setters.get(param.getMiddle().getClass()).accept(st, param);
}

要以类似的方式提取值,您可以使用以下定义:

@FunctionalInterface
interface RSExtractor<T,U,R> {
    R apply(T t, U u) throws SQLException;
}
private Map<Class<?>, RSExtractor<ResultSet, Triple<Integer, Object, Class<?>>, Object>> getters = new HashMap<>();
{
    getters.put(String.class, (rs, param) -> rs.getString(param.getLeft()));
    getters.put(Integer.class, (rs, param) -> rs.getInt(param.getLeft()));
}

public List<Object> get(ResultSet rs) throws SQLException {
    List<Object> results = new ArrayList<>();
    for (Triple<Integer, Object, Class<?>> param : paramList) {
        results.add(getters.get(param.getRight()).apply(rs, param));
    }
    return results;
}

请注意,接口RSExtractor看起来很像接口java.util.function.BiFunction,但此接口允许实现方法抛出SQLException