我在java中编写了自己的2-3-4树。目前,我的代码如下所示:
public class tree234{
private class node{
Comparable data[]=new Comparable[3];
node next[]=new node[4];
}
}
相反,我希望有这样的东西:
public class tree234<T extends Comparable<? super T>>{
private class node{
T[] data=new T[3];//error here!
node[] next=new node[4];
}
}
虽然我知道我无法创建数组(并且有点理解为什么),但我想不出用泛型实现节点类的一种相当简单的方法。有什么建议吗?
答案 0 :(得分:2)
你总是可以做一个明确的演员...
变量T []将在编译类中以Comparable []结束,因为T扩展了Comparable。因此,数组类型必须为Comparable[]
- 您无法将Object
对象分配给Comparable
变量,。
另一种数组类型是Tree234.Node[]
。
public class Tree234<T extends Comparable<? super T>>{
private class Node{
T[] data=(T[]) new Comparable[3]; // need to be a comparable, as the superclass is known.
Node[] next = (Node[]) new Tree234.Node[4];
}
}
答案 1 :(得分:1)
啊,Java-arrays-and-generics,我厌恶你。 虽然使用Lists肯定会解决您的打字问题,但有时候阵列的速度确实是必要的。
反思肯定是一种出路(在这里搜索更多),但我觉得这对我的口味来说太臭了。对于更简单的情况,您可以使用类似我下面的ArrayConstructor接口。如果不是Node类型,我们可以在没有任何警告的情况下解决您的问题,代价是增加了代码详细程度和漏洞抽象(您的类的用户将不得不提供Node和T数组构造函数)。不幸的是,因为节点类型也采用了类型参数,所以我们无法在没有警告的情况下一般地处理这种情况。
interface ArrayConstructor<T> {
T[] constructArray(int size);
}
class Node <T extends Comparable<? super T>>{
private T[] data;
private Node[] next;
Node(ArrayConstructor<T> dataConstructor,
ArrayConstructor<Node<T>> nodeConstructor){
this.data = dataConstructor.constructArray(3);
this.next = nodeConstructor.constructArray(4);
}
}
答案 2 :(得分:1)
除了显而易见的“只使用对象数组并转换返回的值”之外,您还可以使用Array.newInstance(class, size)
并将返回的值转换为T []。您仍然必须禁止警告,因为当前的泛型实现无法避免这种情况,但这种方式是在将对象插入数组时进行类型检查而不是在访问它们时(以前的错误更好)。
在背景中使用反射,这可能不是世界上最高效的东西。
答案 3 :(得分:0)
您应该创建new Comparable[4]
。因为(我相信)这个数组是你的结构的内部,没有人真正关心数组的真实类型。
然后,您可以1)将其分配给T[]
变量(如果您愿意(确保没有任何外部代码访问它,或者它会崩溃),或者2)只需手动将元素转换为T什么时候把它们拿出来无论哪种方式,你都会收到警告。