【发布时间】:2014-03-12 16:03:03
【问题描述】:
我正在尝试教我的学生正确使用 Java 泛型的方法。我正在教授一门数据结构课程,所以我希望他们使用数组和它们自己的链表,而不是使用 Java 集合(例如没有 ArrayList)。一个典型的问题是为 ADT 提供数组实现。这是一个示例,我尝试使用实现为数组的堆来提供优先级队列。我想支持任何类型的数据对象的优先级队列,所以我使用通用的 我从一个界面开始:
public interface PriQue<E> {
void insert(int pri, E data);
E remove(); // return null when empty
boolean isEmpty();
}
然后我实现了它:
public class ArrayHeap<E> implements PriQue<E> {
//private class Entry<E> { hides E of ArrayHeap which means remove fails
private class Entry { // uses E of ArrayHeap
int pri;
E data;
. . .
} // end of Entry
Entry heap[];
int cnt;
public ArrayHeap(int size) {
// heap = new Entry[size]; can not create generic array error
// heap = (Entry[])new Object[size]; blows up on a cast error
heap = (Entry[])new Object[size];
cnt = 0;
}
. . .
public E remove() {
E tmp = (E)heap[--cnt].getData(); //bad don't want to cast
// trickle down code here
return tmp;
}
由于接口是参数化的,我在实现类中使用了相同的泛型——我认为这没问题。
我需要创建一个包含优先级和相应数据项的条目数组。所以我创建了一个私人课程。我的问题从这里开始。如果我不考虑参数,那么因为它是 ArrayHeap 的一部分,它应该在那里选择 E 泛型形式。当我尝试创建一个条目数组时,它会编译但会爆炸。或者,我可以有一个明确的通用参数来输入。如果我选择 E,它将从 ArrayHeap 中“隐藏”E,当我尝试从数组中删除一个 E 时,它不会意识到它与 ArrayHeap E 是同一个 E。如果我将它命名为其他名称,比如 V,那么它就不能将 E 分配给 V,我无法存储任何数据。我认为这是实现数据结构时相当常见的情况。
我试过阅读http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ104
但它不包括嵌套类(主要是关于什么不起作用)
我尝试阅读 Java 集合映射实现的代码,但看不出有什么不同。
【问题讨论】:
-
你用它的自己的泛型类型声明你的内部类——比如
V。然后,当您声明 instance 时,如果内部类使用E-Entry<E> heap[];。这是当您将V设置为等于E时。例如,看看the source forAbstractMap,它具有完全相同的模式。您不能创建通用数组;这似乎是你的主要问题。 -
当您使用
Entry<E>而不是Entry时,remove()如何失败? -
你看过GrepCode上HashMap的源码了吗?它使用带有泛型的嵌套类:grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… 另外,当您说“应该在那里选择 E 泛型形式”时,我不明白您的意思。你能澄清一下吗?
-
@BoristheSpider 是对的。你必须声明它 Entry
heap[]; -
如果我声明条目,请在 @Rohit Jain 评论上