Java Generics和未选中的强制转换

Dre*_*rew 8 java generics

我正在努力解决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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Raf*_*ele 6

在发布的片段中,您需要强制转换,因为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 {}
Run Code Online (Sandbox Code Playgroud)

让我们一步一步解决问题.你希望能够打电话

req.add(new BaseRequest<ExtObj1>());
req.add(new BaseRequest<ExtObj2>());
req.add(new BaseRequest<ExtObj3>());
Run Code Online (Sandbox Code Playgroud)

哪里ExtObj[1|2|3] extends BaseObj.给定List接口:

List<T> {
  void add(T el);
}
Run Code Online (Sandbox Code Playgroud)

我们需要找到一个共同的超类型BaseRequest<ExtObj1>,BaseRequest<ExtObj2>BaseRequest<ExtObj3>.一个超类型是BaseRequest<?>另一个超级类型BaseRequest<? extends BaseObj>.我选择了第二个,因为它是最可能限制的.您应该知道Java BaseRequest<ExtObj1>中不是子类型,BaseRequest<BaseObj>因为泛型是不变的.

现在我们有了mRequests的正确声明,找到API Executor.add()非常简单.顺便说一句,如果你需要的方法体非常简单,你甚至不需要type参数:

public void add(BaseRequest<? extends BaseObj> request) {
  mRequests.add(request);
}
Run Code Online (Sandbox Code Playgroud)