如何使用泛型来处理具有公共超类及其集合的不同类的对象上的已定义操作而不进行转换?

时间:2016-09-02 09:07:25

标签: java generics

让我们有超级班ProxyHost并扩展班级HttpProxyHostHttpsProxyHostsSocks4ProxyHostSocks5ProxyHost

让我们在那些concreet类上有几个集合:

private ArrayList<HttpsProxyHost> httpsProxies = new ArrayList<>();
private ArrayList<Socks5ProxyHost> socks5Proxies = new ArrayList<>();
private ArrayList<HttpProxyHost> httpProxies = new ArrayList<>();
private ArrayList<Socks4ProxyHost> socks4Proxies = new ArrayList<>();

现在我想要的是做类似的事情(下面两​​个变种,都失败了):

    private <T extends ProxyHost> void processRow(Element row, T h, ArrayList<T> httpProxies) {
        h.setIp("someIp");
        h.setOrigin("Some origin");
        h.setPort(1234);
        httpProxies.add(h);
    }

//some other part of app:
    ArrayList<? super ProxyHost> list;
            ProxyHost proxy;
            switch (type) {
            case "HTTP":
                proxy = new HttpProxyHost();
                processRow(row,proxy,httpProxies); // argument missmatch
                break;
            case "HTTPS":
                proxy = new HttpsProxyHost();
                processRow(row,proxy,httpsProxies); //argument missmatch
                break;
            case "SOCKS4":
                list = socks4Proxies; //lists type mismatch
                proxy = new Socks4ProxyHost();
                break;
            case "SOCKS5":
                list = socks5Proxies; //lists type mismatch
                proxy = new Socks5ProxyHost();
                break;
}

所以问题是,为了在添加到concreet集合之前保留那段代码DRY,我想执行一些常见的操作。 如何在不使用超类型和显式转换的情况下使用泛型?有办法吗?

每次我认为我理解通用收藏品,经过一段时间后我发现我实际上并不喜欢;(

编辑:我推出了我现在能想到的最优雅的解决方案:

private <T extends ProxyHost> void processRow(Element row, T h, List<T> list) {
    h.setIp(row.child(0).text());
    h.setPort(Integer.parseInt(row.child(1).text()));
    h.setOrigin("SomeOrigin");
    list.add(h);
}
//and calls:
processRow(row, new HttpProxyHost(), httpProxies);
processRow(row, new HttpsProxyHost(), httpsProxies);
//etc works like charm now

1 个答案:

答案 0 :(得分:1)

要使processRow(row,proxy,httpProxies)有效,T必须解析为HttpProxyHost,否则参数ArrayList<T> httpProxies将与类型{httpProxies的值不兼容1}}。

但是,如果ArrayList<HttpProxyHost>T,则参数HttpProxyHost需要T h,但该值为HttpProxyHost类型proxy即使它实际上包含ProxyHost类型的对象。

通过将HttpProxyHost分配给new HttpProxyHost(),您失去了工作电话所需的兼容性。

你需要:

ProxyHost proxy