Java 数组类型擦除
为什么以下代码可能不是类型安全的(编译器会生成警告)Java 数组类型擦除,java,generics,Java,Generics,为什么以下代码可能不是类型安全的(编译器会生成警告) 类数组类型擦除{ 私有T[]元素; 公共void集合元素(列表元素){ this.elements=(T[])elements.toArray(); } } 我试图考虑代码会失败的任何情况,但到目前为止,只有我失败。原因很简单,因为List#toArray()返回一个对象[],所以这个方法不能保证它会返回T[] 现在,在实践中,这没关系,因为您总是知道它将返回想要的类型 您可以使用@SuppressWarnings(“unchecked”)
类数组类型擦除{
私有T[]元素;
公共void集合元素(列表元素){
this.elements=(T[])elements.toArray();
}
}
我试图考虑代码会失败的任何情况,但到目前为止,只有我失败。原因很简单,因为List#toArray()
返回一个对象[]
,所以这个方法不能保证它会返回T[]
现在,在实践中,这没关系,因为您总是知道它将返回想要的类型
您可以使用@SuppressWarnings(“unchecked”)
来避免出现此警告,这仅仅是因为列表#toArray()
返回一个对象[]
,因此此方法不能保证它会返回T[]
现在,在实践中,这没关系,因为您总是知道它将返回想要的类型
您可以使用
@SuppressWarnings(“unchecked”)
避免由于类型擦除而出现此警告,您可以将List
s强制转换为List
s
ArrayTypeErasure er=新的ArrayTypeErasure();
ArrayTypeErasure erased=er;
List intList=新列表();//编译警告,但是
增加(1);
已删除。setElements(intList);
由于类型擦除,您可以将List
s强制转换为List
s
ArrayTypeErasure er=新的ArrayTypeErasure();
ArrayTypeErasure erased=er;
List intList=新列表();//编译警告,但是
增加(1);
已删除。setElements(intList);
首先,请注意数组在运行时知道其组件类型,但泛型类的实例在运行时不知道泛型类型参数。列表
无法在运行时创建运行时类型为T[]
的数组对象,因为它不知道运行时的T
是什么。采用一个数组参数的List#toArray()
方法使用传入数组实例的运行时类型在运行时构造相同组件类型的数组。但是没有参数的列表#toArray()
总是创建一个运行时类型为对象[]
的数组。因此,elements.toArray()
计算的数组实例的运行时类型始终为Object[]
Object[]
不是T[]
的子类型(当T
不是Object
时),因此将此数组分配给this。编译时类型T[]
的元素,是错误的。但是,它不会立即导致任何异常,因为t
的擦除是Object
,所以t[]
的擦除是Object[]
,将Object[]
分配给Object[]
是可以的。只要您确保从不将this.elements
中包含的对象作为t[]
暴露到此对象之外,它就不会引起任何问题。但是,如果将this.elements
中包含的对象作为类型T[]
公开给类外(例如,将this.elements
返回为类型T[]
的方法,或者如果将this.elements
设置为公共或受保护字段),则类外的调用方可能期望T
为特定类型,这可能会导致类强制转换异常
例如,如果有一个方法将this.elements
作为类型T[]
返回:
public T[] getElements() {
return this.elements;
}
ArrayTypeErasure<String> foo = ...
String[] bar = foo.getElements();
然后有一个调用者持有ArrayTypeErasure
,它调用.getElements()
,它需要一个字符串[]
。当它尝试将结果分配给字符串[]
时,将导致类强制转换异常,因为对象的运行时类型是对象[]
:
public T[] getElements() {
return this.elements;
}
ArrayTypeErasure<String> foo = ...
String[] bar = foo.getElements();
ArrayTypeErasure foo=。。。
字符串[]bar=foo.getElements();
首先,请注意数组在运行时知道其组件类型,但泛型类的实例在运行时不知道泛型类型参数。列表
无法在运行时创建运行时类型为T[]
的数组对象,因为它不知道运行时的T
是什么。采用一个数组参数的List#toArray()
方法使用传入数组实例的运行时类型在运行时构造相同组件类型的数组。但是没有参数的列表#toArray()
总是创建一个运行时类型为对象[]
的数组。因此,elements.toArray()
计算的数组实例的运行时类型始终为Object[]
Object[]
不是T[]
的子类型(当T
不是Object
时),因此将此数组分配给this。编译时类型T[]
的元素,是错误的。但是,它不会立即导致任何异常,因为t
的擦除是Object
,所以t[]
的擦除是Object[]
,将Object[]
分配给Object[]
是可以的。只要您确保从不将this.elements
中包含的对象作为t[]
暴露到此对象之外,它就不会引起任何问题。但是,如果将this.elements
中包含的对象作为类型T[]
公开给类外(例如,将this.elements
返回为类型T[]
的方法,或者如果将this.elements
设置为公共或受保护字段),则类外的调用方可能期望T
为特定类型,这可能会导致类强制转换异常
例如,如果有一个方法将this.elements
作为类型T[]
返回:
public T[] getElements() {
return this.elements;
}
ArrayTypeErasure<String> foo = ...
String[] bar = foo.getElements();
然后有一个调用者持有ArrayTypeErasure
,它调用.getElements()
,它需要一个字符串[