3

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);

此代码将抛出 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)

这是为什么?

4

2 回答 2

5

ArrayStoreException当尝试将不正确类型的对象存储到数组中时,会发生这种情况。

代码在做什么?

在给出的示例代码中,该CollectionUtil.transform方法采用 aCollection并执行元素的就地转换,这意味着s 从原始(例如 a )Object中取出并放回相同的.CollectionListCollection

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

可能出了什么问题?

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

我怀疑Listcreated byArrays.asList得到了 a 的支持String[],因为那很可能是ArrayStoreException. 运行调试器确认了这一点,因为它由String[5]. (使用 Eclipse,在 Windows 上的 JRE 6 上运行。)

这个例子说明了什么?

这是一个典型的例子,说明缺乏泛型如何允许编写非类型安全的代码,因此在运行时出现问题。如果代码是用泛型编写的(Apache Commons Collection 支持它),这些类型的问题将在编译时被发现。

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

可以做什么?

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

这个方法支持泛型,所以它是类型安全的,而且它返回一个新的事实Collection意味着类型可以通过转换来改变。

于 2010-01-16T03:13:13.120 回答
1

Arrays.asList方法使用与新列表实例的支持数组相同的提供数组。API 代码如下所示:

public static <T> List<T> asList(T... a) {
    return new ArrayList<T>(a);
}

调用StringUtils.split创建一个String[]传递给Arrays.asList方法的。这会将您可以插入新列表实例的元素类型限制为仅String对象。

CollectionUtils类支持 2 种不同类型的转换:

  1. 就地转换 -在这种情况下,输入集合实例将使用转换后的值进行更新。所有transform()变体都属于这一类。当使用由数组支持的集合类型(例如 ArrayList)时,只有当转换后的值与支持数组类型兼容时,转换才能成功。这解释了您所看到的异常。

  2. 不合适的转换 -在这种情况下,输入集合永远不会更新。而是将转换后的值收集在单独的集合实例中。所有collect()变体都属于第二类。collect() 方法的重载版本要么接受输出集合作为参数,要么如果没有指定单独的集合,则创建一个新的列表实例来收集转换后的值。

根据您尝试解决的场景,您应该使用第二种类型的转换并调用其中一种collect()变体。

于 2014-04-19T16:11:57.527 回答