在类的构造函数中初始化泛型类型的数组,而不必传递Class <t>参数</t>

时间:2011-12-11 02:32:37

标签: java generics

我有课:

class SomeClass<T extends SomeInterface>{

   private T[] myArray;

   public SomeClass()
   {
       // I want to initialize myArray in here to a default size of 100
       myArray = new T[100];  // this gives an error
   }

}

我知道我可以通过在构造函数中要求一个参数来解决这个问题:

class SomeClass<T extends SomeInterface>{

   private T[] myArray;

   public SomeClass(Class<T> clazz)
   {       
       myArray= (T[]) Array.newInstance(clazz, 100);
   }

}

但是没有场景必须两次传递泛型参数。

换句话说,为了从类SomeClass实例化一个对象,我将不得不这样做:

SomeClass<SomeOtherClass> obj = 
      new SomeClass<SomeOtherClass>(SomeOtherClass.class);

我用c#编程,Java似乎不友好。我甚至不明白为什么不能将Object[]数组转换为SomeOtherClass[]数组。在c#中,这将是可能的......

所以我的问题是如何避免传递SomeOtherClass.class参数,以便能够在类的构造函数中构造泛型类型的数组...

3 个答案:

答案 0 :(得分:4)

虽然Shakedown列出了您的问题的修复程序,但请允许我解释为什么创建通用数组不是类型安全的。

我将使用Effective Java 2nd Ed。

中的示例说明原因
// Why generic array creation is illegal - won't compile! 
List<String>[] stringLists = new List<String>[1]; // (1) 
List<Integer> intList = Arrays.asList(42); // (2) 
Object[] objects = stringLists; // (3) 
objects[0] = intList; // (4) 
String s = stringLists[0].get(0); // (5)
  
      
  • 让我们假装创建通用数组的第1行是合法的。

  •   
  • 第2行创建并初始化包含单个的List<Integer>   元件。

  •   
  • 第3行将List<String>数组存储到Object数组中   变量,这是合法的,因为数组是协变的。

  •   
  • 第4行将List<Integer>存储到Object数组的唯一元素中   之所以成功是因为泛型是通过擦除实现的:运行时类型   一个List<Integer>实例只是List,而运行时类型是。{   List<String>[]实例为List[],因此不会生成此分配   ArrayStoreException现在我们遇到了麻烦。我们存储了一个   List<Integer>实例进入一个声明只保留的数组   List<String>个实例。

  •   
  • 在第5行,我们从中检索唯一的元素   此数组中的唯一列表。编译器自动转换   检索到String的元素,但它是一个整数,所以我们得到一个   ClassCastException在运行时。为了防止这种情况发生   发生,第1行(创建一个通用数组)生成一个   编译时错误。

  •   

答案 1 :(得分:1)

是的,您必须像这样传递.class才能使其发挥作用。

您可以避免所有这些,只需使用ArrayList<T>即可。当您需要数组形式时,可以使用:(T[]) myArrayList.toArray()

答案 2 :(得分:0)

java中的所有类型都是Object类的子类,因此可以使用它来实现。

public StackArray(int size){
    dataStack = (T[])new Object[size];
}