我在Java泛型的这一方面苦苦挣扎。希望有人可以帮助我看看方法。

我有一个包含对象列表的类。这段代码有效,但是我想摆脱这种类型。如何使它更通用?

public class Executor {
    List<BaseRequest<BaseObj>> mRequests = new ArrayList<BaseRequest<BaseObj>>();

    public Executor() {
    }

    @SuppressWarnings("unchecked")
    public <T extends BaseObj> void add(final BaseRequest<T> request) {
        mRequests.add((BaseRequest<BaseObj>) request);
    }

    public void execute() {
        for (BaseRequest<BaseObj> r : mRequests) {
            // DO SOMETHING WITH r
        }
    }
}

最佳答案

在发布的代码段中,您需要进行强制转换,因为BaseRequest<? extends BaseObj>不是BaseRequest<BaseObj>的子类型,并且由于类型擦除而无法在运行时检查强制转换,这就是编译器向您发出警告的原因。但是,如果您更改mRequests的声明:

public class Executor  {

    List<BaseRequest<? extends BaseObj>> mRequests = new ArrayList<>();

    public Executor() {
    }

    public <T extends BaseObj> void add(final BaseRequest<T> request) {
        mRequests.add(request);
    }

    public void execute() {
        for (BaseRequest<? extends BaseObj> r : mRequests) {
            // DO SOMETHING WITH r
        }
    }
}

class BaseRequest<T> {}

class BaseObj {}

让我们逐步解决问题。您希望能够打电话
req.add(new BaseRequest<ExtObj1>());
req.add(new BaseRequest<ExtObj2>());
req.add(new BaseRequest<ExtObj3>());

其中ExtObj[1|2|3] extends BaseObj。给定List接口(interface):
List<T> {
  void add(T el);
}

我们需要找到BaseRequest<ExtObj1>BaseRequest<ExtObj2>BaseRequest<ExtObj3>的通用父类(super class)型。一种父类(super class)是BaseRequest<?>,另一种是BaseRequest<? extends BaseObj>。我选择了第二个,因为它是最严格的限制。您应该知道在Java中BaseRequest<ExtObj1>不是BaseRequest<BaseObj>的子类型,因为泛型是不变的。

既然我们对mRequests有了正确的声明,那么找到Executor.add()的API就很简单了。顺便说一句,如果您需要的方法主体真的那么简单,那么您甚至不需要type参数:
public void add(BaseRequest<? extends BaseObj> request) {
  mRequests.add(request);
}

10-07 20:38