Why does Java ArrayList use per-element casting instead of per-array casting?

前端 未结 4 698
梦如初夏
梦如初夏 2021-01-07 18:47

What happens inside Java\'s ArrayList (and probably many other classes) is that there is an internal Object[] array = new Object[n];, to w

4条回答
  •  天命终不由人
    2021-01-07 19:20

    It's more complicated than that: generics are erased in byte code, and the erasure of T[] is Object[]. Likewise, the return value of get() becomes Object. To retain integrity of the type system, a checked cast is inserted when the class is actually used, i.e.

    Integer i = list.get(0);
    

    will be erased to

    Integer i = (Integer) list.get(0);
    

    That being the case, any type check within ArrayList is redundant. But it's really beside the point, because both (T) and (T[]) are unchecked casts, and incur no runtime overhead.

    One could write a checked ArrayList that does:

    T[] array = Array.newInstance(tClass, n);
    

    This would prevent heap pollution, but at the price of a redundant type check (you can not suppress the synthentic cast in calling code). It would also require the caller to provide the ArrayList with the class object of the element type, which clutters its api and makes it harder to use in generic code.

    Edit: Why is generic array creation forbidden?

    One problem is that arrays are checked, while generics are unchecked. That is:

    Object[] array = new String[1];
    array[0] = 1; // throws ArrayStoreException
    
    ArrayList list = new ArrayList();
    list.add(1); // causes heap pollution
    

    Therefore, the component type of an array matters. I assume this is why the designers of the Java language require us to be explicit about which component type to use.

提交回复
热议问题