让我们有超级班ProxyHost
并扩展班级HttpProxyHost
,HttpsProxyHosts
,Socks4ProxyHost
,Socks5ProxyHost
让我们在那些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
答案 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