为什么android studio警告我关于输入类型的通用数组创建

时间:2016-02-26 10:59:33

标签: java android generics

我的android项目中有一个适配器,它接受一个可重复使用的地图,为简单起见,它保留了一组数据。

private Entry<String, String>[] mData;

public MyAdapter(@NonNull Map<String, String> data) {
    mData = (Entry<String, String>[]) data.entrySet().toArray();
}

现在我想让它更有效率并摆脱未经检查的警告,所以我改为使用特定的数组类型

mData = data.entrySet().toArray( new Entry<String, String>[ data.size() ] );

new Entry<String, String>[ data.size() ]部分现已标记为&#34; 通用数组创建&#34;没有进一步的信息。 为什么这是非法的?

我知道Java有类型擦除,并且泛型导致不同类型(例如解释here),但上面的代码行似乎对我来说应该是合法的。

1 个答案:

答案 0 :(得分:1)

  

为什么这是非法的?

因为数组是协变的。假设您能够编译以下代码:

Entry<String, String>[] array = new Entry<String, String>[ isoMap.size() ];
Object[] objArray = array;

// Does not throw an ArrayStoreException.
objArray[0] = new AbstractMap.SimpleEntry<>(Integer.valueOf(0), Integer.valueOf(0));
String key = array[0].getKey();

在运行时,赋值不会抛出ArrayStoreException,因为AbstractMap.SimpleEntryAbstractMap.SimpleEntry<Integer, Integer>的运行时类型)与Map.Entry是协变的(运行时类型为{ {1}}) - 但是当您尝试执行最后一行时,它会因Entry<String, String>而失败,因为它们的密钥是ClassCastException,而不是Integer

但是,您现在必须担心每个元素可能是错误的类型 - 给定String的引用,您无法准确知道数组的初始化方式或更新,因此以错误的方式访问任何给定元素可能会导致运行时异常。

(当我说“错误的方式”时,我用Entry<String, String>[]之类的东西来约束String key = array[0].getKey() - 所有对象都有array[0].toString()方法,所以不会尝试转换)。

避免这种情况最安全的方法就是使通用数组的创建非法。

请注意,这与非泛型但协变数组的情况不同:

toString()

因为该赋值会抛出String[] array = new String[1]; Object[] objArray = array; // Throws an ArrayStoreException. objArray[0] = Integer.valueOf(0); ,所以错误类型的值永远不会添加到数组中。

因此,虽然在尝试将值放入数组时仍然需要担心ArrayStoreException,但在从数组中读取值时,您不必担心ArrayStoreException