我的问题涉及将泛型引入遗留Java类。 我想要生成的下面代码中的遗留类是ClientObjectProxy和ClientObjectContainer。 ClientObject保持不变。 为简单起见,我将所有类放入一个外部类中。
现在,在遗留代码中,对未参数化的ClientObjectProxyContainer实例上的方法ClientObjectProxyContainer.getProxies()进行了多次调用。
通过引入泛型现有代码,如循环4中将不再编译,需要将调用提取到局部变量,如循环1,或者需要使用类似于循环2的带问号的声明。 新代码应该使用参数化变量,如循环3中。
我的问题是,这是我的方法,将现有代码更改为循环1或循环2,还是有一种不修改遗留代码的方法?
由于
扬
import java.util.ArrayList;
import java.util.List;
public class GenericForumsExample {
/**
* This class is unchanged
*/
private class ClientObject {
}
/**
* @param <T> Type of the ClientObject behind this proxy
*/
private class ClientObjectProxy<T extends ClientObject> {
}
/**
* @param <T> Type of the ClientObject contained in this collection
*/
private class ClientObjectProxyContainer<T extends ClientObject> {
//Previous signature was:
// public List<ClientObjectProxy> getProxies(){
// New signature is the following
public List<ClientObjectProxy<T>> getProxies(){
return new ArrayList<ClientObjectProxy<T>>();
}
}
public void testScenario() {
ClientObjectProxyContainer proxyContainer = new ClientObjectProxyContainer();
List<ClientObjectProxy> proxies = proxyContainer.getProxies(); // Just a compiler warning
// Loop 1
for (ClientObjectProxy proxy : proxies) { // Compiler OK
//Do something...
}
// Loop 2
ClientObjectProxyContainer<?> clientObjectProxyContainer = new ClientObjectProxyContainer();
for (ClientObjectProxy<?> proxy : clientObjectProxyContainer.getProxies()) {
//Do something...
}
// Loop 3
for (ClientObjectProxy<ClientObject> proxy : new ClientObjectProxyContainer<ClientObject>().getProxies()) {
//Do something...
}
// Loop 4
// Compiler fails on next code line
// incompatible types
// found : java.lang.Object
// required: GenericForumsExample.ClientObjectProxy
for (ClientObjectProxy proxy : proxyContainer.getProxies()) {
//Do something...
}
}
}
答案 0 :(得分:1)
在处理泛型的代码中,尽量避免使用原始类型。当您使用这些类型时,通常会丢失比预期更多的类型信息,就像在这种情况下发生的那样。
最后一个循环中的调用proxyContainer.getProxies()
实际上返回List
(因为proxyContainer
是原始类型,所有与其类型相关的泛型都被删除,包括方法签名中的泛型) 。如果你遍历原始的List
,你只会得到Object
,所以存在编译错误。您可以通过在for循环中编写(List<ClientObjectProxy>)proxyContainer.getProxies()
来解决此问题(当然,您会收到警告)。
因此,使用通配符代替原始类型通常更清晰。在已经“泛化”的代码中,如果您没有具体类型,请不要使用原始类型ClientObjectProxyContainer
,但始终使用ClientObjectProxyContainer<?>
。此类型具有基本相同的含义,但在使用时不会导致忽略所有泛型类型。
使用通配符作为proxyContainer
类型时,getProxies()
的结果类型将为List<ClientProxyObject<?>>
而不是List
,因此您可以{{1} s out out it(但在这里,也喜欢使用ClientProxyObject
!)。
答案 1 :(得分:0)
如果您介绍Generics,我更喜欢循环1方法。然后您不必担心类型检查。