2009-10-19 17 views
1

我得到一个ClassCastException当Eclipse建议,我的代码应该是这样的..ClassCastException异常时日食“固定”我的代码

我有一个名为科尔特类。

ArrayList<Kort> kort = new ArrayList<Kort>(); 

然后我用toArray()和Eclipse建议它应该看起来像:Kort[] array = (Kort[])kort.toArray();

但它给了我这个例外:ClassCastException! :(

+2

FYI ...如果您在代码行的开头添加四个空格,Markdown会将这些字符放入“代码格式”中,您的<>将显示出来。 – karlgrz 2009-10-19 21:26:32

回答

2

你可以做的是:

Kort[] array = kort.toArray(new Kort[kort.size()]); 

这被认为是更好,因为它使阵列上的类型安全。如果你不在乎/希望如果没有参数,toArray()方法返回一个Object []数组。

+1

因为类型擦除是...烦人。 – RHSeeger 2009-10-19 21:31:38

+0

工作,我会用.. thx! – Johannes 2009-10-19 21:44:54

+1

@RHSeeger - 实际上,类型擦除只是外围连接到这个。 toArray()和toArray(Object)之间的区别自从它引入以来就一直是Collections框架的一部分。详细解释请参阅我的答案。 – 2009-10-20 01:58:43

2

使用

kort.toArray(new Kort[kort.size()]); 
3

我的建议是:

kort.toArray(new Kort[0]) 

从技术上讲,这可能比给出正确的大小要慢一些。但是,您不需要提及集合变量名称两次,因此出错的可能性较小。这也更容易阅读。作为奖励,它也适用于并发集合,在那里调用size并不真正具有很大的意义。

但是,最好的方法是避免使用引用数组,如果可能的话。

+1

有趣的是默认IDEA会给你一个这样的语法警告,所以我已经习惯了指定尺寸,但是你是对的,它是一个微型优化,显然不是一个好的方法 – Yishai 2009-10-20 01:15:24

2

问题的根源在于java.util.Collection API中的Object[] toArray()Object[] toArray(Object[])方法之间的差异。

第一种形式分配正确大小的数组来保存集合的成员,然后将成员引用分配到数组中。由于集合类不知道实际成员的类型(请参见下面的注释),API指定结果为Object[]的实例;即如同使用new Object[size]分配一样。

第二种形式将一个数组作为参数,它将(通常)成为存储集合成员引用的参数。因此,程序通过传递所需类型的数组来确定结果的类型。如果提供的数组足够大以容纳收集元素,则方法将返回提供的数组实例。如果不是,则为所提供的数组实例分配一个新的数组。 (这可以通过使用Array.newInstance(clazz, size)其中clazz是提供的数组的组件类沉思完成的。需要注意的是类型参数不是用来做这个...它不能使用。)

所以发生的是,Eclipse是不足够聪明地知道,真正纠正你的错误是使用不同的方法过载。为了进行这种修正,它需要“知道”两种形式的方法的具体语义。这是一个高难度的海事组织。

经验教训是,Eclipse的建议更正只是建议......并不保证是正确的修复。

注意:由于类型擦除,集合类不知道要在toArray()情况下创建的适当数组类。有关类型如何实例化的信息不适用于实现toArray的类。但考虑到通常可以插入Collection<T>而不是T(通过忽略“不安全类型”编译器警告),这可能是好东西结果类型是Object[]

此问题早于泛型类型;自从在Java 1.2中引入集合框架以来,这种方法的两种形式就已经存在了。

编辑:在评论@Thilo建议,如果Java从一开始就支持泛型,就不会出现这个问题。我的回答是,它不是这样发生的,我们不能说如果他们有的话会发生什么。但我们可以说,与Java的泛型,因为他们目前定义这是不可能的,没有重新设计集合的API。

具体而言,泛型类无法确定实际类型已被用作给定实例的类型参数。没有这些信息,它就无法知道要实例化的正确数组类型。在实践中,如果您希望泛型类型创建类型参数或某些相关类型的实例,则必须设计API,以便相关方法可以运行时访问实际参数类型的对象Class。例如,实际的Class对象可以作为构造函数参数提供。

+0

至少toArray ()方法只需要一个类对象并创建数组本身,即使使用类型擦除。它可以确保类对象是集合的正确类型,如toArray(类类型); – Yishai 2009-10-20 23:41:23

+0

@义海 - 同意了,但这与现有的[ T [] toArray(T [] a)]方法没有多大区别。我想Sun的人们认为,对于'toArray'而言,一个新的重载(相对次要的)优势超过了它所引入的兼容性问题。 – 2009-10-21 00:01:18

0

kort.toArray(new Kort[kort.size()]); 

(Kort[])kort.toArray(); 

的是,在情况下,你地图集合为空,将所得到阵列应的对象类型的零长度阵列将抛出异常另一个优点如果改为Kort。

使用kort.toArray(new Kort[kort.size()]);可确保即使集合为空仍然返回的数组是所需的类型。