如何初始化泛型对象数组?Java N叉树节点类类型转换报错解决
错误原因
Java的数组是运行时保留具体类型的协变类型,而泛型基于类型擦除实现,你遇到的报错有两个核心诱因:
- 直接创建
Object[]后强制转换为NaryTreeNode<T>[]是不合法的:Object[]的运行时类型就是Object数组,无法向下转型为NaryTreeNode数组。 - 直接写
new NaryTreeNode<T>[3]会编译失败:泛型的类型参数<T>在运行时会被擦除,JVM无法获取到泛型的具体类型信息,不允许直接创建泛型数组。
解决方案
方案1:使用ArrayList替代原生数组(最推荐)
Java标准库的ArrayList天然支持泛型,无需手动处理扩容、类型转换,代码容错性更高,修改后完整代码如下:
import java.util.ArrayList; public class NaryTreeNode<T> { private T data; private ArrayList<NaryTreeNode<T>> children; public NaryTreeNode (T data) { this.data = data; // 初始化容量为3,和你原来的逻辑对齐 children = new ArrayList<>(3); } public void addChild (NaryTreeNode<T> node) { children.add(node); } // 可按需加获取子节点、获取子节点数量等方法 public int getNumChildren() { return children.size(); } public NaryTreeNode<T> getChild(int index) { if (index < 0 || index >= children.size()) { return null; } return children.get(index); } public static void main (String[] args) { NaryTreeNode<String> node = new NaryTreeNode<>("a"); NaryTreeNode<String> temp = new NaryTreeNode<>("b"); node.addChild(temp); System.out.println("子节点数量:" + node.getNumChildren()); System.out.println("第一个子节点数据:" + node.getChild(0).data); } }
方案2:泛型数组实现(如果必须用原生数组)
如果你的需求必须用原生数组实现,可以创建无泛型的原始类型NaryTreeNode数组后再强转,添加@SuppressWarnings注解压制 unchecked 警告即可,修改后代码如下:
public class NaryTreeNode<T> { private T data; int numChildren; NaryTreeNode<T>[] children; public NaryTreeNode (T data) { this.data = data; numChildren = 0; children = null; } @SuppressWarnings("unchecked") public void addChild (NaryTreeNode<T> node) { if (children == null) { // 这里创建原始类型NaryTreeNode数组,而不是Object数组 children = (NaryTreeNode<T>[]) new NaryTreeNode[3]; } if (numChildren == children.length) { expandCapacity(); } children[numChildren] = node; numChildren++; } @SuppressWarnings("unchecked") public void expandCapacity() { // 同样创建原始类型NaryTreeNode数组 NaryTreeNode<T>[] larger = (NaryTreeNode<T>[]) new NaryTreeNode[numChildren + 3]; for (int i = 0; i < numChildren; i++) { larger[i] = children[i]; } children = larger; } public static void main (String[] args) { NaryTreeNode<String> node = new NaryTreeNode<>("a"); NaryTreeNode<String> temp = new NaryTreeNode<>("b"); node.addChild(temp); System.out.println("子节点数量:" + node.numChildren); System.out.println("第一个子节点数据:" + node.children[0].data); } }
这个方案的原理是:泛型擦除后NaryTreeNode<T>的原始类型就是NaryTreeNode,所以创建原始类型数组再强转是运行时安全的,仅需要压制编译阶段的 unchecked 警告即可。
内容的提问来源于stack exchange,提问作者Will01liMEH
相关产品推荐
相关产品推荐

