andyInCambridge
andyInCambridge

Reputation: 1225

java generic casting in generic classes

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

Answers (4)

Judge Mental
Judge Mental

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

maks
maks

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

stefan bachert
stefan bachert

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

Peter Lawrey
Peter Lawrey

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

Related Questions