java generic casting in generic classes

最后都变了- 提交于 2020-01-04 11:03:27

问题


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.


回答1:


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.




回答2:


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



回答3:


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 >




回答4:


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.



来源:https://stackoverflow.com/questions/13960601/java-generic-casting-in-generic-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!