通用列表转换为数组

时间:2016-11-08 12:17:03

标签: java arrays list generics

假设我有以下课程

public class A <T>{

    private T [] datas;
    // more code here ...
}

我希望利用构造函数初始化数组。假设我有以下构造函数

public A(T element){....}

Java不允许我使用像

这样的东西
datas = new T[10]

它会抱怨我无法创建T 的通用数组 但我仍然可以使用类似的工作:

 @SuppressWarnings("unchecked")
    public A(T element){

       List<T> datasList = new ArrayList<T>();
       datasList.add(element);
       datas =(T[]) datasList.toArray();
    }

我收到编译器的警告,说明为什么我必须添加@SuppressWarnings,但我的观点与toArray方法文档中的以下注释有关(请看一下图片)

enter image description here

它谈到返回的数组是安全的这是否意味着使用此方法是安全的?如果不是为什么?在构造函数中进行此类初始化的更好方法是什么?我还想在重载的构造函数中考虑一个T元素的变量列表,例如

公开A(T ...元素){....}。

2 个答案:

答案 0 :(得分:2)

您可以使用以下方法创建通用数组的实例:

public A(T element){
  int length = 10;
  datas  = (T[])Array.newInstance(element.getClass(), length);
}

但是,如果elementT的子类,则存在问题,例如如果你这样称呼它:

A<Number> numberA = new A<>( Integer.valueOf(1) );

此处TNumber,但element的等级为Integer。 为了减轻这种情况,您可以传递类型为T的vararg数组,例如像这样:

//firstElement only exists to force the caller to provide at least one element
//if you don't want this then just use the varargs array
A(T firstElement, T... furtherElements){      
  int length = 10;
  Class<?> elementClass = furtherElements.getClass().getComponentType();      
  datas  = (T[])Array.newInstance( elementClass, length);
}

由于varargs总是产生一个数组(即使是长度为0),你将得到一个类型为T的数组,并且可以得到它的组件类型。

因此,上述情况numberA.datas将是Number[]数组,而不是Integer[]数组。

答案 1 :(得分:0)

您可以传递泛型,但无法调用新的T (or new T[ ])。 请记住,编译后泛型已经消失,所以它实际上只有在编写代码时才有用。知道它在运行时已经消失了,很明显新的T()不能被称为泛型,T在运行时被删除。

这样做是安全的,因为您可以完全控制创建该列表,只接受您的泛型类型的对象。

一种更好的方式(imho)是创建一个静态方法,因为它纯粹是输入 - >输出。您必须在方法返回类型之前声明您的泛型:

public < T > T[ ] toArray(T... objects) { ... }