Java中List<int[]>转int[][]时toArray为何传入new int[0][]
为什么
List<int[]>转二维数组时toArray要传入new int[0][] 首先得先搞清楚Collection接口定义的两个toArray重载的区别:
- 无参版本
toArray()的返回值固定是Object[]类型,哪怕你集合里存的全是int[]元素,返回的数组运行时类型也是Object数组,直接强转成int[][]会抛出ClassCastException,完全没法用。 - 带泛型参数的版本
<T> T[] toArray(T[] a),会返回和你传入参数运行时类型完全一致的数组,用来存放集合内的元素,这才是能得到指定类型数组的正确重载。
这个泛型版本对传入的参数a有明确的处理逻辑:
- 如果你传入的数组长度 >= 集合实际元素个数,方法会直接把集合元素按顺序填入这个数组,数组里超出集合长度的位置会填充
null,最后把这个数组直接返回。 - 如果你传入的数组长度 < 集合实际元素个数,方法不会用你传入的数组装元素,只会通过反射拿到这个数组的类型信息,内部新建一个同类型、长度刚好等于集合元素总数的新数组,填完元素后返回新数组。
回到你看到的写法ans.toArray(new int[0][]),这么写的原因很直接:
- 先满足类型要求:你需要的返回值是
int[][]类型,所以必须传入一个int[][]类型的数组作为参数,泛型才能正确推断返回值类型,不会出现类型转换错误。如果你错传成别的类型(比如new String[0][]),运行时会直接抛ArrayStoreException。 - 传长度0是通用惯用法:写
new int[0][]相当于明确告诉方法“我只给你提供类型信息,你自己根据集合实际大小创建长度刚好匹配的数组返回”,不需要我们提前手动调用ans.size()创建指定长度的数组。
之前有说法认为传new int[ans.size()][]性能更好,毕竟省了方法内部反射创建数组的开销,但现在主流JVM的JIT优化已经能对0长度数组的传参做专门优化,实际性能和传指定长度数组没有明显差距;而且0长度写法更简洁,也能避免多线程场景下,调用size()之后集合元素个数变动,导致提前创建的数组长度不合适、反而被废弃浪费的问题。
你不用纠结“参数里第一维长度写0会不会返回空数组”——你传的这个长度为0的数组本身根本不会被用来存数据,它只是个传递类型信息的“类型令牌”而已,方法内部发现它长度不够,会自己新建长度匹配的数组返回。
内容的提问来源于stack exchange,提问作者Shivam Taneja
相关产品推荐
相关产品推荐

