假设我有以下课程
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方法文档中的以下注释有关(请看一下图片)
它谈到返回的数组是安全的。 这是否意味着使用此方法是安全的?如果不是为什么?在构造函数中进行此类初始化的更好方法是什么?我还想在重载的构造函数中考虑一个T元素的变量列表,例如
公开A(T ...元素){....}。
答案 0 :(得分:2)
您可以使用以下方法创建通用数组的实例:
public A(T element){
int length = 10;
datas = (T[])Array.newInstance(element.getClass(), length);
}
但是,如果element
是T
的子类,则存在问题,例如如果你这样称呼它:
A<Number> numberA = new A<>( Integer.valueOf(1) );
此处T
为Number
,但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) { ... }