当eclipse“修复”我的代码时ClassCastException

时间:2009-10-19 21:21:25

标签: java eclipse exception

当eclipse建议我的代码应该是那样的时候,我得到一个ClassCastException。

我有一个名为Kort的课程。

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

然后我使用toArray(),而eclipse建议它应该是这样的:Kort[] array = (Kort[])kort.toArray();

但是它给了我这个异常:ClassCastException! :(

5 个答案:

答案 0 :(得分:3)

我的建议是:

kort.toArray(new Kort[0])

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

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

答案 1 :(得分:2)

使用

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

答案 2 :(得分:2)

你能做的是:

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

这被认为是更好的,因为它保持阵列上的类型安全。如果你不关心/想要那个,那么就忽略这个建议。不带参数的toArray()方法返回一个Object []数组。

答案 3 :(得分:2)

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

第一个表单分配一个正确大小的数组来保存集合的成员,然后将成员引用分配给数组。由于集合类不知道成员的实际类型(请参阅下面的注释),因此API指定结果是Object[]的实例;即好像是使用new Object[size]分配的。

第二种形式将数组作为参数(通常)存储集合成员引用的位置。因此,程序通过传递所需类型的数组来确定结果的类型。如果提供的数组足以容纳集合元素,toArray方法将返回提供的数组实例。如果不是,则为新数组分配与提供的数组实例相同的类型。 (这可以使用Array.newInstance(clazz, size)反射性地完成,其中clazz是提供的数组的组件类。请注意,类型参数不用于执行此操作...并且不能使用它。)

所以正在发生的事情是Eclipse不够聪明,不知道对你的错误的真正纠正是使用不同的方法重载。为了进行这种修正,需要“知道”toArray方法的两种形式的特定语义。这是一个很高的订单IMO。

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

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

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

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

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

答案 4 :(得分:0)

的另一个优点
kort.toArray(new Kort[kort.size()]);

(Kort[])kort.toArray();

如果您的kort集合为空,则生成的to数组应为对象类型的零长度数组,如果将该类型转换为Kort,则会抛出异常。

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