我不明白为什么我会在下面的代码中获得 ClassCastException
:
for(int i = 0; i < k.t.length; i++)
问题是在方法addElement
中我用类型为T的对象替换数组元素。在我看来,数组应该是类型为T的对象。编译器并没有为此提出抗议。
但是在运行时JVM无法转换,尽管在数组中实际上是类型为T的对象(如果在String下面),为什么JVM不能使用多态?
但是当我将T[] t;
更改为Object[] t;
并删除构造函数中的强制转换,它运行正常,没有任何错误,为什么?
public class MyCollection<T> {
T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.t.length; i++)
System.out.println(k.t[i]);
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
答案 0 :(得分:4)
问题是你正在向Object[]
投射T[]
,然后你暴露了底层数组。这完全有效的唯一原因是因为T
的类型擦除是Object
。但由于在我们的情况下T
被解释为String
,当我们从外部访问数组时,我们会尝试将其强制转换为String[]
,这是不正确的。为了避免此问题,您应该将数组设为私有,并提供访问器方法来检索元素。通过这样做,您只需将单个元素转换为正确的类型,而无需对底层数组进行假设。
public class MyCollection<T> {
private T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
T getElement(int index) {
return t[index];
}
int getLength() {
return t.length;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.getLength(); i++)
System.out.println(k.getElement(i));
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
请注意,Java的Collection
接口演示了相同的行为。无论Object[]
的类型如何,Collection.toArray()都会返回E
。唯一可用的解决方法是Collection.toArray(T[]),您必须在其中传递具有固定类型的数组,然后可以填充或复制该数组。
答案 1 :(得分:1)
再次检查问题的界限。在我看来,由于以下原因将抛出异常:
for(String s : (String[])k.t)
你在这里试图转换为String [],而数组被定义为Object []:
t = (T[]) new Object[size];
答案 2 :(得分:0)
您可以使用反射创建一个新的数组实例,以避免ClassCastException
示例:强>
import java.lang.reflect.Array;
public class MyCollection<T> {
T[] t;
MyCollection(Class<T> clazz, int size) {
t = (T[]) Array.newInstance(clazz, size);
}
boolean addElement(T e, int i) {
if (i < t.length - 1) {
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss) {
MyCollection<String> k = new MyCollection<String>(String.class, 3);
k.addElement("a", 0);
k.addElement("b", 1);
k.addElement("c", 2);
for (int i = 0; i < k.t.length; i++)
System.out.println(k.t[0]);
}
}