Reputation: 1225
I'm writing a simple implementation of a generic max heap. If I write
public class FastMaxHeap<T>{
T[] data;
int size;
static final int HEAP_SIZE = 10000;
@SuppressWarnings("unchecked")
public FastMaxHeap(){
data = (T[]) new Object[HEAP_SIZE];
size = 0;
}
}
it compiles. Now to actually implement the heap, i.e. write maxHeapify(), I need to be able to compare two T's. One option that a priori seems possible would be to tell the compiler that T implements Comparable. But if I type replace < T > with < T implements Comparable > the compiler complains -- how can I do this?
Alternatively, I could define a class
public class HasValue{
int value;
public HasValue(int value){
this.value = value;
}
}
and in theory I should then be able to compare two HasValue objects like x.value > y.value. But if I type
public class FastMaxHeap<T extends HasValue>{
T[] data;
int size;
static final int HEAP_SIZE = 10000;
@SuppressWarnings("unchecked")
public FastMaxHeap(){
data = (T[]) new Object[HEAP_SIZE];
size = 0;
}
}
I now get a ClassCastException. What is going on here? Java generics hurt my brain.
Upvotes: 2
Views: 224
Reputation: 5239
Your heap should accept a Comparator< T > as a constructor argument. Problem solved. Client can use any type he wants. You can also supply a simple overload which infers the comparator implementation for types T that already implement Comparable.
Upvotes: 0
Reputation: 6006
It is better to have type token to create arrays like this
public class FastMaxHeap<T>{
T[] data;
int size;
static final int HEAP_SIZE = 10000;
@SuppressWarnings("unchecked")
public FastMaxHeap(Class<T> clazz){
data = (T[])Array.newInstance(clazz, HEAP_SIZE);
size = 0;
}
}
In such way you will have no ClassCastExceptions in runtime
And also: < T implements Comparable >
is not correct, correct one is < T extends Comparable >
Upvotes: 0
Reputation: 9624
You may try this one (not compiled, yet)
public class FastMaxHeap<T extends HasValue>{
HasValue[] data;
int size;
static final int HEAP_SIZE = 10000;
public FastMaxHeap(){
data = new HasValue[HEAP_SIZE];
size = 0;
}
}
Upvotes: 0
Reputation: 533870
In the first case T extends Object
which is erased to Object
at runtime.
In the second case T extends HasValue
is erased to HasValue
so you need to have.
data = (T[]) new HasValue[HEAP_SIZE];
IMHO It is needlessly pedantic that Java doesn't allow new T[HEAP_SIZE]
to do what you have to do anyway.
Upvotes: 5