我认为这里肯定有些微妙的事情我不知道。考虑以下:
public class Foo<T> {
private T[] a = (T[]) new Object[5];
public Foo() {
// Add some elements to a
}
public T[] getA() {
return a;
}
}
假设您的main方法包含以下内容:
Foo<Double> f = new Foo<Double>();
Double[] d = f.getA();
您将得到一个
CastClassException
,消息为java.lang.Object
无法转换为java.lang.Double
。谁能告诉我为什么?我对
ClassCastException
的理解是,当您尝试将对象强制转换为无法强制转换的类型时会抛出该错误。也就是说,对于不是实例的子类(引用文档)。例如。:Object o = new Double(3.);
Double d = (Double) o; // Working cast
String s = (String) o; // ClassCastException
看来我可以做到。如果
a
只是一个T
而不是一个T[]
数组,我们可以获取a
并将其强制转换。为什么数组会破坏这一点?谢谢。
最佳答案
Foo<Double> f = new Foo<Double>();
使用泛型类Foo的此版本时,然后对于成员变量
a
,编译器实质上采用以下行:private T[] a = (T[]) new Object[5];
并用
T
替换Double
来得到这个:private Double[] a = (Double[]) new Object[5];
您不能从Object转换为Double,因此不能转换为ClassCastException。
更新和说明:实际上,在运行一些测试代码之后,ClassCastException比这更微妙。例如,这个main方法可以正常工作,没有任何异常:
public static void main(String[] args) {
Foo<Double> f = new Foo<Double>();
System.out.println(f.getA());
}
当您尝试将
f.getA()
分配给Double[]
类型的引用时,会发生此问题:public static void main(String[] args) {
Foo<Double> f = new Foo<Double>();
Double[] a2 = f.getA(); // throws ClassCastException
System.out.println(a2);
}
这是因为有关成员变量
a
的类型信息在运行时已删除。泛型仅在编译时提供类型安全性(我在最初的文章中以某种方式忽略了这一点)。所以问题不在于private T[] a = (T[]) new Object[5];
因为在运行时这段代码确实
private Object[] a = new Object[5];
当方法
getA()
的结果(在运行时实际上返回Object[]
)的结果分配给类型为Double[]
的引用时,就会发生问题-该语句引发ClassCastException,因为无法将对象强制转换为Double。更新2 :回答您的最后一个问题“为什么数组会破坏它?”答案是因为语言规范不支持通用数组创建。 See this forum post for more-为了向后兼容,在运行时对T的类型一无所知。
关于java - 泛型,数组和ClassCastException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/372250/