2

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.

2
  • Why not just store Comparables? Commented Dec 19, 2012 at 20:36
  • +1 for "Java generics hurt my brain." Commented Dec 19, 2012 at 20:39

4 Answers 4

5

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.

Sign up to request clarification or add additional context in comments.

6 Comments

I deleted my answer in favor of yours.
@stefanbachert The casting will work provided the component type of the new array is a sub-type of what T extends.
It's not "needlessly pedantic"; it's very important. Try to return data from a method in your class with return type T[] and see what happens.
@newacct Can you be more specific?
I am assuming you mean you want Java to allow new T[HEAP_SIZE] to mean (T[])new HasValue[HEAP_SIZE];. But that is unsafe so it is important to force the user to have to explicitly override it.
|
0

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;
   }
}

1 Comment

If you drop the casting you don't need the suppress warning
0

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 >

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.