7

我非常熟悉 Scheme 和 Haskell 等函数式语言。我正在尝试解决 Java 中的一个问题并在苦苦挣扎,可能是因为我仍然处于功能性思维模式。

我想写:

public void doQueryAndStoreData(String query, <? extends Collection> storeIn) {
    /* make a jdbc query, get ResultSet */
    ResultSet rset = ...;
    ProcessResultSet proc = new ProcessResultSet();
    proc.process(rset, storeIn);
    /* clean up */
}

使用如下界面:

private interface IProcessResultSet<C> {
    public void process(ResultSet rset, C storeIn);
}

和一个实现接口的类,如:

private class ProcessResultSet implements IProcessResultSet<? extends Collection> {
    public void process(ResultSet rset, Map storeIn) {
        /* do something */
    }

    public void process(ResultSet rset, List storeIn) {
        /* do something else */
    }
}

这样第一个方法可以process根据给出的类型调用适当的方法storeIn

在 Haskell 我可以写

class Storeable c a where
    store :: a -> c a -> c a

doQueryAndStoreData :: Storeable c a => ResultSet a -> c a -> c a
doQueryAndStoreData (ResultSet rs) coll = foldr store coll rs

并为Storeable我想要存储的任何集合类型提供实例ResultSet

这是Java中的正确方法吗?因为我觉得我在为实现这一目标而与语言作斗争。

4

3 回答 3

2

不幸的是,你不能这样做。编译器必须在编译时知道此调用绑定到哪个方法。如果要根据对象的运行时类型来决定调用哪个方法,则必须手动检查:

你能做的最多:

private class ProcessResultSet implements IProcessResultSet<? extends Collection> {

    @Override
    public void process(ResultSet rset, Collection storeIn) {
        if (storeIn instanceof Set) {
            return processSet(rset, (Set) storeIn);
        } else if (storeIn instanceof List) {
            return processList(rset, (List) storeIn);
        } else {
            throw new IllegalArgumentException("Unimplemented storage type");
        }
    }


    public void processSet(ResultSet rset, Set storeIn) {
        /* do something */
    }

    public void processList(ResultSet rset, List storeIn) {
        /* do something else */
    }
}
于 2013-01-24T16:54:47.483 回答
2

不,Java 不这样做。

您需要执行以下操作:

public <T> void doQueryAndStoreData(
    String query,
    T storeIn,
    ResultSetProcessor<T> processor
) {

或者更有可能:

public void doQueryAndStoreData(
    String query,
    ResultSetHandler handler // may contain processor and storeIn
) {

我希望我不需要提到 SQL 注入漏洞是一件坏事。(在 JavaMap中也不是 a Collection(它在 C# 中,但 C#Collection不是很有用)。)

于 2013-01-24T17:00:34.550 回答
0
private class ProcessResultSet implements IProcessResultSet<? extends Collection> {

    public void process(ResultSet rset, Object storeIn) 
    {
        if ( storeIn instanceof Map)
            processMap(rset,(Map) storeIn);
        else if (storeIn instanceof List)
            processList(rset,(List) storeIn);   
        else
            System.out.println("Unsupported input type.");
    }

    public void processMap(ResultSet rset, Map storeIn) {
        /* do something */
    }

    public void processList(ResultSet rset, List storeIn) {
        /* do something else */
    }
}
于 2013-01-24T16:55:52.647 回答