Java 使用CollectionUtils转换列表会引发ArrayStoreException
Java代码:Java 使用CollectionUtils转换列表会引发ArrayStoreException,java,collections,apache-commons,Java,Collections,Apache Commons,Java代码: Transformer TRANSFORM_TO_INTEGER = new Transformer() { public Object transform(Object input) { Integer i = new Integer((String) input); return i; } }; String begin = "1,2,3,4,5"; List strList = Arrays.asList(StringUti
Transformer TRANSFORM_TO_INTEGER = new Transformer() {
public Object transform(Object input) {
Integer i = new Integer((String) input);
return i;
}
};
String begin = "1,2,3,4,5";
List strList = Arrays.asList(StringUtils.split(begin, ","));
CollectionUtils.transform(strList, TRANSFORM_TO_INTEGER);
此代码将引发ArrayStoreException:
java.lang.ArrayStoreException
at java.util.Arrays$ArrayList.set(Arrays.java:2360)
at java.util.AbstractList$ListItr.set(AbstractList.java:488)
at org.apache.commons.collections.CollectionUtils.transform(CollectionUtils.java:434)
为什么会这样?当试图将不正确类型的对象存储到数组中时,会发生这种情况
代码在做什么?
在给出的示例代码中,该方法采用a并对元素执行就地转换,这意味着将对象
从原始集合
(例如a)中取出并放回相同的集合
的代码获取一个字符串
,并将其转换为一个整数
——这是这里的核心问题——应用转换时,对象的类型正在发生变化
会出什么问题?
如前所述,CollectionUtil.transform
将使用给定的转换器
,对集合
中的每个元素执行转换,并将其存储回原始的集合
,即strList
我怀疑由创建的列表
由字符串[]
支持,因为这可能是阵列存储异常
的来源。运行调试器确认了这一点,因为它由字符串[5]
支持。(使用Eclipse,在Windows上的JRE 6上运行。)
这个例子说明了什么?
这是一个主要的例子,说明缺乏泛型如何允许编写类型不安全的代码,从而在运行时出现问题。如果代码是用泛型编写的(Apache Commons Collection支持它),那么这些类型的问题将在编译时被捕获
底线——不能转换列表中的类型元素
——如果列表
包含字符串
s,则只应返回字符串
可以做什么?
作为替代方案,它有一个方法,该方法接受给定的集合
,并返回一个由
此方法支持泛型,因此是类型安全的,并且它返回一个新的
集合
,这意味着类型可以通过转换进行更改 Arrays.asList方法使用与新列表实例的备份数组相同的提供数组。API代码如下所示:
public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a);
}
公共静态列表asList(T…a){
返回新的ArrayList(a);
}
调用StringUtils.split
将创建一个String[]
,并将其传递给Arrays.asList
方法。这将限制可以插入到新列表实例中的元素类型仅限于String
对象
CollectionUtils
类支持两种不同类型的转换:
transform()
变体都属于此类别。使用由数组支持的集合类型(例如ArrayList)时,只有当转换的值与支持的数组类型类型兼容时,转换才能成功这解释了您看到的异常。collect()
变体都属于第二类。collect()方法的重载版本要么接受输出集合作为参数,要么在未指定单独集合的情况下创建新的列表实例来收集转换后的值根据您试图解决的场景,您应该使用第二种类型的转换并调用
collect()
变体之一。可以将其更改为使用Arrays.asList(xxx)
,或Arrays.asList(新对象[]{xxx})
。最好在整个过程中使用泛型,这会使就地转换变得可疑。最好放弃Apache commons集合。