如何解决Java:使用接口指针转换为泛型
| 在下面的示例代码中,两个类EventA
和EventB
都实现了interface Historical
。当这些对象之一作为参数传递时,Java可以自动将“ 0”或“ 1”转换为“ 5”,如下面的“ 6”方法一样。但是,当引入泛型即Java时,Java将不再能够进行转换。从List<EventA>
到List<Historical>
-除非使用List<? extends Historical>
声明目标函数(在这种情况下为findClosestValidEventIndex
)。
有人可以解释为什么会这样吗?在我看来,在泛型中非常使用接口应该自动暗示“ 11”。
public class SampleApplication {
public interface Historical {
public DateTime getDate();
}
public static class EventA implements Historical {
private DateTime date;
@Override
public DateTime getDate() {
return date;
}
}
public static class EventB implements Historical {
private DateTime date;
@Override
public DateTime getDate() {
return date;
}
}
private static int findClosestValidEventIndex(List<Historical> history,DateTime when) {
// do some processing
return i;
}
private static int examineEvent(Historical event){
return j;
}
public static void main(String[] args) {
DateTime target = new DateTime();
// AOK
EventA a = new EventA(target);
int idy = examineEvent(a);
// Type Error --- Unless
List<EventA> alist = new ArrayList<EventA>();
int idx = findClosestValidEventIndex(alist,target);
}
}
解决方法
因为表示只能支持EventA类型的对象或其子类型的列表。这样的列表不能包含添加到其中的EventB。
因此,Java不允许您将List 作为有效参数传递给需要List 的方法参数。毕竟,尽管Historical和EventA与Historical和EventB之间存在继承关系,但List 和List 之间没有这种关系。
List<EventA>
不是List<Historical>
。想像:
List<EventA> list = ...;
List<Historical> h = (List<Historical>) list;
h.add(new EventB()); //type-safety of list is compromised
for (EventA evt : list) { // ClassCastException - there\'s an EventB in the lsit
...
}
List<? extends Historical>
表示\“ Historical的一个特定子类型的列表”,您不能在其中添加任何内容,因为在编译时您不知道类型是什么。
, 它不能总是使用extends
,因为有时您可能需要其他行为。
当将通用对象用作生产者时,需要协方差(extends
)。当将通用对象用作使用者时,您需要使用方差(super
)。实际规则是“生产者-扩展,消费者-超级”:
public void getEventFromHistory(List<? extnds Historical> history) {
Historical e = history.get(0); // history is a producer of e
}
public void addEventAToHistory(List<? super EventA> history) {
history.add(new EventA()); // history is a consumer
}
// Possible usage
List<EventA> sequenceOfEventsA = ...;
addEventAToHistory(sequenceOfEventsA);
List<Historical> history = ...;
addEventToHistory(history);
, 您不能将绑定到子类的集合传递给绑定到超类的集合的方法参数。
这是因为声明“列表历史”从定义上来说意味着它是一个能够容纳任何扩展“历史”的列表。这意味着您可以将EventA或EventB或这些类型的混合添加到此集合中。
但是List 版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。