使用CollectionUtils转换List会抛出ArrayStoreException

jac*_*see 3 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(StringUtils.split(begin, ","));
CollectionUtils.transform(strList, TRANSFORM_TO_INTEGER);
Run Code Online (Sandbox Code Playgroud)

此代码将抛出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)
Run Code Online (Sandbox Code Playgroud)

这是为什么?

coo*_*ird 5

ArrayStoreException当尝试存储不正确类型的对象时,会发生这种情况.

代码在做什么?

在给出的示例代码中,该CollectionUtil.transform方法采用a Collection并执行元素的就地变换,这意味着Objects从原始Collection(例如a List)中取出并放回到相同的位置Collection.

a的代码Transformer采用a String并将其转换为Integer- 这是核心问题 - 应用变换时对象的类型正在发生变化.

怎么可能出错?

如前所述,CollectionUtil.transform将使用给定的Transformer并对每个元素执行转换Collection并将其存储回原始的Collection,即strList.

我怀疑List创建的Arrays.asList是由a支持的String[],因为那可能是它的来源ArrayStoreException.运行调试器确认,因为它由a支持String[5].(使用Eclipse,在Windows上运行JRE 6.)

这个例子说明了什么?

这是缺少泛型如何允许编写非类型安全的代码的一个主要示例,因此,在运行时出现问题.如果代码是用泛型编写的(并且Apache Commons Collection支持它),那么这些类型的问题将在编译时捕获.

底线 - 一个不能转换类型元素List- 如果List包含Strings,则Transformer.transform应该只返回一个String.

可以做些什么?

作为替代方案,Google Collections有一个Collections2.transform方法,它接受一个给定的Collection并返回一个Collection由a转换的方法Function.

这种方法支持泛型,因此它是类型安全的,并且它返回一个新的Collection意思是类型可以通过转换来改变.