Dav*_*ave 20 java generics java-6
我正在使用Java 6.
我无法让我的内部类使用与其封闭类相同的泛型类.目前我有
public class TernarySearchTree < T > {
...
protected class TSTNode < T > {
// index values for accessing relatives array
protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3;
protected char splitchar;
protected TSTNode < T > [] relatives;
private T data;
protected TSTNode(char splitchar, TSTNode < T > parent) {
this.splitchar = splitchar;
relatives = new TSTNode[4];
relatives[PARENT] = parent;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我收到了警告
类型参数T隐藏类型T.
如果我从内部类中删除类型参数(即<T>从protected class TSTNode<T>行中删除),那么我在行上得到一个编译错误relatives = new TSTNode[4].
我怎样才能把一切都搞定?
Ita*_*man 11
你可以:
<T>从中删除类型参数TSTNode(即,使其非通用) - 它仍然可以访问外部<T>.
将<T>类中的type参数重命名TSTNode为(例如)U.
[UPDATE]
以下是重写代码的四种不同方法.所有人都编译.我认为你应该考虑使用EnumMap(参见下面的第4版).
版本1:在内部类中使用不同名称的类型参数.你需要使用List而不是数组.
public class TernarySearchTree<T> {
protected class TSTNode<U> {
// index values for accessing relatives array:
protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3;
protected char splitchar;
protected List<TSTNode<U>> relatives;
private U data;
protected TSTNode(char splitchar, TSTNode<U> parent) {
this.splitchar = splitchar;
relatives = new ArrayList<TSTNode<U>>();
for (int i = 0; i < HIKID; ++i) { // Allocate 4 slots in relatives
relatives.add(null);
}
relatives.set(PARENT, parent);
}
}
private TSTNode<T> node; // When you use it, pass T as U
public TernarySearchTree() {
node = new TSTNode<T>(',', null); // When you use it, pass T as U
}
}
Run Code Online (Sandbox Code Playgroud)
版本2:从封闭类继承T.
public class TernarySearchTree<T> {
protected class TSTNode {
// index values for accessing relatives array:
protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3;
protected char splitchar;
protected List<TSTNode> relatives;
private T data;
protected TSTNode(char splitchar, TSTNode parent) {
this.splitchar = splitchar;
relatives = new ArrayList<TSTNode>();
for (int i = 0; i < HIKID; ++i) { // Allocate 4 slots in relatives
relatives.add(null);
}
relatives.set(PARENT, parent);
}
}
private TSTNode node;
public TernarySearchTree() {
node = new TSTNode(',', null);
}
}
Run Code Online (Sandbox Code Playgroud)
版本3:使用Map(而不是List)
public class TernarySearchTree<T> {
protected class TSTNode {
// index values for accessing relatives array:
protected static final int PARENT = 0, LOKID = 1, EQKID = 2, HIKID = 3;
protected char splitchar;
protected Map<Integer, TSTNode> relatives;
private T data;
protected TSTNode(char splitchar, TSTNode parent) {
this.splitchar = splitchar;
// Create a hash map. No need to pre-allocate!
relatives = new HashMap<Integer, TSTNode>();
relatives.put(PARENT, parent); // set -> put
}
}
private TSTNode node;
public TernarySearchTree() {
node = new TSTNode(',', null);
}
}
}
Run Code Online (Sandbox Code Playgroud)
版本4:将索引定义为枚举+使用EnunMap(而不是哈希映射)
public class TernarySearchTree<T> {
protected static enum Index {
PARENT, LOKID, EQKID, HIKID;
}
protected class TSTNode {
protected char splitchar;
protected EnumMap<Index, TSTNode> relatives;
private T data;
protected TSTNode(char splitchar, TSTNode parent) {
this.splitchar = splitchar;
// Create an EnumMap.
relatives = new EnumMap<Index, TSTNode>(Index.class);
relatives.put(Index.PARENT, parent);
}
}
private TSTNode node;
public TernarySearchTree() {
node = new TSTNode(',', null);
}
}
Run Code Online (Sandbox Code Playgroud)
[更新2] 要记住一件事:使用EnumMap而不是序数索引
关于从内部类中删除T时通用数组创建的编译错误:
因为它是一个非静态内部类,所以它在外部类的type参数的范围内。这意味着它还通过其外部类的type参数隐式地参数化
因此,当您编写TSTNode它时,基本上意味着TernarySearchTree<T>.TSTNode(这里的T是外部T)。因此TSTNode仍然是泛型类型(即使您没有明确看到任何括号),并且创建泛型类型的数组也会失败。
您可以TSTNode通过手动限定名称来引用的原始类型TernarySearchTree.TSTNode。
new TernarySearchTree.TSTNode[4]答案也是如此。
您将得到一个未经检查的警告,可以忽略该警告(这是通用类型数组所必需的)
PS从内部类中删除类型参数几乎肯定是正确的选择,因为Java中的非静态内部类隐式引用了外部类的实例。因此,它已经用外部T进行了参数化。如果您只想使用相同的T,请不要声明另一个T。