I'm using Java 6.
I'm having trouble getting my inner class to use the same generic class as its enclosing class. Currently I have
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;
}
}
}
Right now I get the warning
The type parameter T is hiding the type T
If I remove the type parameter from the inner class (i.e. remove the <T>
from teh protected class TSTNode<T>
line), then I get a compile error on the line relatives = new TSTNode[4]
.
How can I make everything right?
You can either:
remove the <T>
type parameter from TSTNode
(i.e., make it non-generic) - it will still have access to the outer <T>
.
rename the <T>
type parameter in class TSTNode
to (say) U
.
[UPDATE]
Below are four different ways to rewrite your code. All of them compile. I think you should consider the use of an EnumMap
(see Version 4, below).
Version 1: use a differenly named type parameter in the inner class. you need to use a List instead of an array.
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
}
}
Version 2: inherit T from enclosing class
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);
}
}
Version 3: use a Map (instead of a 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);
}
}
}
Version 4: define the indices as an enum + use an EnunMap (instead of a hash map)
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);
}
}
[Update 2] One thing to keep in mind: Use EnumMap instead of ordinal indexing