如何在java中创建类型安全的泛型数组?
我想在java中创建一个通用数组,以维护java通常提供的类型安全性 我正在使用以下代码:如何在java中创建类型安全的泛型数组?,java,arrays,generics,Java,Arrays,Generics,我想在java中创建一个通用数组,以维护java通常提供的类型安全性 我正在使用以下代码: class Stack<T> { private T[] array = null; public Stack(Class<T> tClass, int size) { maximumSize = size; // type unsafe //array = (T[])new Object[maximumSize]; this.array = (T[]
class Stack<T> {
private T[] array = null;
public Stack(Class<T> tClass, int size) {
maximumSize = size;
// type unsafe
//array = (T[])new Object[maximumSize];
this.array = (T[])java.lang.reflect.Array.newInstance(tClass,maximumSize);
}
类堆栈{
私有T[]数组=null;
公共堆栈(类tClass,int-size){
最大尺寸=尺寸;
//类型不安全
//数组=(T[])新对象[maximumSize];
this.array=(T[])java.lang.reflect.array.newInstance(tClass,maximumSize);
}
此代码类型安全吗?如果是,为什么?如果是类型安全的,为什么我需要强制转换?该方法的返回类型为Object
。因此,您不能直接将其分配给Object
以外的任何对象。因此,您需要强制转换
该方法委托给一个本机方法,该方法
创建具有指定组件类型和长度的新数组
因此,它正在创建类型为T
的数组
假设数组
声明为
T[] array;
,由类
参数和使用相同类型变量的强制转换保证
您应该添加
@SuppressWarnings("unchecked")
在源代码中用注释解释上述原因。请始终注释为什么禁止其警告的强制转换是安全的。因为我们知道泛型是在编译时检查的,所以,我的朋友
newInstance(tClass,size);返回对象并进行类型转换,如果数组不是T[]然后可能会出现编译时错误,因为数组。newInstance
返回一个对象,它需要强制转换。在这种情况下,编译器将始终发出警告。这是泛型的限制。由于基元类对象的原因,它不是类型安全的。例如,我可以通过以下方式创建一个新堆栈:
new Stack<Boolean>(boolean.class, 10);
实际上有点类型安全,但原因不同:这是由于擦除。例如,您不能将新对象[size]
强制转换为数字[]
,但强制转换从未在数组上发生。这种情况会在一段时间后发生,比如从方法返回数组的元素时(在这种情况下,该元素被强制转换)。如果尝试执行类似于将数组返回到对象外部的操作,它将引发异常
通常情况下,解决方案不是一般地键入数组。而是执行以下操作:
class Stack<E> {
Object[] array = new Object[10];
int top;
void push(E elem) {
if(top == array.length)
array = Arrays.copyOf(array, array.length * 2);
array[top++] = elem;
}
E pop() {
@SuppressWarnings("unchecked")
E elem = (E)array[--top]; // type safe cast
array[top] = null;
return elem;
}
}
为什么我会收到未经检查的警告?您正在进行未经检查的强制转换,因此使用它会收到警告。@giuseppes,因为编译器不能保证它。方法规范应该是这样的。请注意,如果有专门用于引用类型数组的newInstance
,编译器可以保证它。static t[]newInstance(c类,int size)
注意,这样做会引发基元类型的异常。例如,int.Class
是一个类
,因此将int[]
强制转换为整数[]
。没有一种方法可以通用地表示基元。这就是它可能不安全的原因。在上面的代码中(T[])
简单地强制转换到对象[]
,因为类型T在编译时是未知的。因此数组
必须是对象[]类型
(或简单地对象
)。如果返回类型为T[]的值
然后,在调用时,当方法的返回值被赋值或使用时,编译器将向适当的类型抛出一个隐藏的强制转换。你能更新你的代码使其编译吗?T
来自哪里?数组如何声明?例如,你认为这是一个静态方法吗(这只是Array#newInstance
的包装器)或者Array
是字段,T
是类的类型参数?非常详细的答案!
class Stack<E> {
Object[] array = new Object[10];
int top;
void push(E elem) {
if(top == array.length)
array = Arrays.copyOf(array, array.length * 2);
array[top++] = elem;
}
E pop() {
@SuppressWarnings("unchecked")
E elem = (E)array[--top]; // type safe cast
array[top] = null;
return elem;
}
}
Stack(Class<T> tClass, int size) {
if(tClass.isPrimitive())
throw new IllegalArgumentException();
// ...
}