我正在努力解决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
}
}
}
答案 0 :(得分: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 {}
让我们一步一步解决问题。你希望能够打电话
req.add(new BaseRequest<ExtObj1>());
req.add(new BaseRequest<ExtObj2>());
req.add(new BaseRequest<ExtObj3>());
其中ExtObj[1|2|3] extends BaseObj
。鉴于List接口:
List<T> {
void add(T el);
}
我们需要找到BaseRequest<ExtObj1>
,BaseRequest<ExtObj2>
和BaseRequest<ExtObj3>
的常见超类型。一个超类型为BaseRequest<?>
,另一个超级类型为BaseRequest<? extends BaseObj>
。我选择了第二个,因为它是最可能限制的。你应该知道在Java BaseRequest<ExtObj1>
中不是BaseRequest<BaseObj>
的子类型,因为泛型是不变的。
现在我们有了mRequests的正确声明,找到Executor.add()
的API非常简单。顺便说一句,如果您需要的方法体非常简单,那么您甚至不需要类型参数:
public void add(BaseRequest<? extends BaseObj> request) {
mRequests.add(request);
}
答案 1 :(得分:0)
警告不是错误。有警告,所以你检查是否有错误,因为它可能不会被自动检查。您应该检查它,然后使用注释注意已经检查过警告。
在您的情况下,警告BaseRequest<T>
不等同于BaseRequest<BaseObj>
。
示例:
public class NumberWrapper<N extends Number> {
private N value;
public void setValue(N value) {
this.value = value;
}
}
public class MainClazz {
private NumberWrapper<Integer> wrappedNumber = new NumberWrapper<Integer>();
public void run() {
Number n = externalSource.getNumber();
wrappedNumber.setValue(n); // <-- Error. What if getNumber returns a double?
}
}
您可以出现此错误,具体取决于您完成/整合所显示代码的方式。