首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在编译时捕获ArrayStoreException

在编译时捕获ArrayStoreException
EN

Stack Overflow用户
提问于 2014-02-18 16:06:20
回答 4查看 633关注 0票数 3

考虑一下下面对Java的ArrayList#toArray方法的测试。请注意,我从这个有用的回答中借用了代码。

代码语言:javascript
复制
public class GenericTest {
    public static void main(String [] args) {
        ArrayList<Integer> foo = new ArrayList<Integer>();
        foo.add(1);
        foo.add(2);
        foo.add(3);
        foo.add(4);
        foo.add(5);
        Integer[] bar = foo.toArray(new Integer[10]);
        System.out.println("bar.length: " + bar.length);

        for(Integer b : bar) { System.out.println(b); }

        String[] baz = foo.toArray(new String[10]);       // ArrayStoreException
        System.out.println("baz.length: " + baz.length);
    }
}

但是,请注意,当尝试将一个ArrayStoreException放入一个String[]中时,会有一个String[]

产出:

代码语言:javascript
复制
$>javac GenericTest.java && java -cp . GenericTest
bar.length: 10
1
2
3
4
5
null
null
null
null
null
Exception in thread "main" java.lang.ArrayStoreException
        at java.lang.System.arraycopy(Native Method)
        at java.util.ArrayList.toArray(Unknown Source)
        at GenericTest.main(GenericTest.java:16)

能否通过Java泛型在编译时防止此错误?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-02-18 16:20:37

ArrayStoreException之所以存在,正是因为它的类型系统无法正确地处理这种情况(IIRC,当Generics出现时,用与集合框架相同的方式对数组进行修改已经太晚了)。

因此,在编译时通常无法防止此问题的发生。

当然,您可以创建内部API来包装这些操作,以减少意外错误类型的可能性。

另请参阅:

票数 7
EN

Stack Overflow用户

发布于 2014-02-18 16:09:42

List#toArray(T[])是一个泛型方法,声明为

代码语言:javascript
复制
<T> T[] toArray(T[] a);

因此,类型参数要么是从给定数组的类型推断出来的,要么是以<Type>符号作为方法调用的前缀。

所以你可以

代码语言:javascript
复制
String[] baz = foo.<Integer>toArray(new String[10]); // doesn't compile

但我觉得这是你能做的最好的了。

但从这个意义上说,您可以清楚地看到IntegerString不匹配(反之亦然)。

请注意,这是一个记录在案的异常。

ArrayStoreException -如果指定数组的运行时类型不是此列表中每个元素的运行时类型的超级类型

所以我不认为你应该在编译时找到它。

票数 2
EN

Stack Overflow用户

发布于 2014-02-18 18:22:24

由于兼容性原因,无法更改方法Collection.toArray

但是,对于您自己的代码,您可以创建一个(更多)类型安全的帮助器方法,如果因此使用您的方法,它可以保护您免受ArrayStoreException的侵害:

代码语言:javascript
复制
public static <T> T[] toArray(List<? extends T> list, T[] t) {
    return list.toArray(t);
}

此方法将拒绝与您问题的示例情况匹配的String[] s=toArray(new ArrayList<Integer>(), new String[0]);,但请注意数组子类型规则:它不会拒绝。

代码语言:javascript
复制
Object[] s=toArray(new ArrayList<Integer>(), new String[0]);

由于前泛型,“String[]Object[]的子类”规则。这不能用现有的Java语言解决。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21859099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档