2

我的问题与将泛型引入遗留 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...
        }
    }

}
4

2 回答 2

1

在处理泛型的代码中,尽量避免使用原始类型。当您使用这些类型时,您通常会丢失比您预期更多的类型信息,就像在这种情况下发生的那样。

最后一个循环中的调用proxyContainer.getProxies()实际上返回 a List(因为proxyContainer是原始类型,所有与其类型相关的泛型都被删除,包括方法签名中的泛型)。如果你遍历一个 raw List,你只会得到Objects ,所以会出现编译错误。您可以通过在 for 循环中写入来解决此问题(List<ClientObjectProxy>)proxyContainer.getProxies()(您当然会收到警告)。

因此,使用通配符而不是原始类型通常更清楚。在已经“泛化”的代码中,永远不要使用原始类型ClientObjectProxyContainer,但ClientObjectProxyContainer<?>如果您没有具体类型,则始终使用。该类型的含义基本相同,但在使用时不会导致所有泛型类型都被忽略。

当为 of 类型使用通配符时proxyContainer,结果类型 ofgetProxies()List<ClientProxyObject<?>>不是 just List,因此您可以将ClientProxyObjects 去掉(但在这里,也更喜欢使用ClientProxyObject<?>!)。

于 2012-04-11T12:51:28.680 回答
0

如果您引入泛型,我更喜欢 Loop 1 方法。那么您不必担心类型检查。

于 2012-04-11T12:53:54.783 回答