Java泛型T展开式链表转二维数组出现ClassCastException如何解决
问题原因
- Java的数组是具化类型(reified type),运行时会保留元素类型信息,
Object[][]和Integer[][]是完全独立的类型,不能互相强转 - 你当前的代码只是在编译期骗过了泛型检查,实际创建的还是
Object[][],运行时调用方拿到后向下转型就会抛出ClassCastException
解决方法(不修改返回类型T[][])
可以通过反射工具java.lang.reflect.Array创建对应泛型类型的二维数组,建议给方法补充一个Class<T>入参用来明确泛型的实际类型,这是最稳妥的实现方案,修改后的代码如下:
import java.lang.reflect.Array; public T[][] getArrayOfBlocks(Class<T> elementType) { Node node = this.first; // 用反射创建对应类型的二维数组 @SuppressWarnings("unchecked") T[][] result = (T[][]) Array.newInstance(elementType, this.nNodes, this.arraySize); for(int i = 0; i < this.nNodes; i++) { for(int j = 0; j < this.arraySize; j++) { if(node.a[j] != null) { result[i][j] = node.a[j]; } } node = node.next; } return result; }
调用的时候传入对应类型的Class即可,比如T为Integer时就调用getArrayOfBlocks(Integer.class)。
可选无入参方案(不推荐)
如果不想修改方法的入参结构,也可以取链表中第一个非空元素的类型来创建数组,但存在局限性:如果链表全为空元素会触发空指针异常,需要额外做兼容处理,代码示例如下:
import java.lang.reflect.Array; public T[][] getArrayOfBlocks() { Node node = this.first; // 遍历查找第一个非空元素获取类型 T sample = null; while (node != null && sample == null) { for (int k = 0; k < this.arraySize; k++) { if (node.a[k] != null) { sample = (T) node.a[k]; break; } } node = node.next; } if (sample == null) { // 全空场景可根据业务需求调整返回逻辑 return (T[][]) new Object[0][0]; } node = this.first; @SuppressWarnings("unchecked") T[][] result = (T[][]) Array.newInstance(sample.getClass(), this.nNodes, this.arraySize); for(int i = 0; i < this.nNodes; i++) { for(int j = 0; j < this.arraySize; j++) { if(node.a[j] != null) { result[i][j] = node.a[j]; } } node = node.next; } return result; }
内容的提问来源于stack exchange,提问作者pizzatorta
相关产品推荐
相关产品推荐

