Java 8可编译Java 16报错:Enumeration泛型强制转换失败问题排查
报错原因
DefaultMutableTreeNode的children()方法返回值类型为Enumeration<TreeNode>,而代码中直接将其强转为Enumeration<DefaultMutableTreeNode>,触发了泛型检查规则的差异:
- 泛型本身是不变的:哪怕
DefaultMutableTreeNode是TreeNode的子类,Enumeration<DefaultMutableTreeNode>也不属于Enumeration<TreeNode>的子类,二者不存在继承关系,原则上不允许直接强转。 - Java 8对这类泛型强转的编译检查较为宽松,仅会输出
unchecked警告,不会阻断编译;Java 9及之后版本逐步收紧了泛型编译校验规则,到Java 16后这类不规范的泛型强转直接判定为编译错误。
修复方案
两种常用修复方式,均可以同时兼容Java 8和Java 16环境:
方案1:调整泛型声明,遍历元素时单独转型(推荐)
无需添加抑制警告注解,编译完全合规,运行风险更低:
protected void onCalculate() { final ConsoleMapperForTree cm = new ConsoleMapperForTree(); cm.setVisible(true); cm.getConsole().setFont(new Font("Tahoma", 0, 20)); final DefaultMutableTreeNode root = (DefaultMutableTreeNode)this.tree.getModel().getRoot(); // 调整枚举泛型声明为通配符形式,匹配children()返回值类型 final Enumeration<? extends TreeNode> enmFclt = root.children(); while (enmFclt.hasMoreElements()) { // 取出元素时单独转型 final DefaultMutableTreeNode fclt = (DefaultMutableTreeNode) enmFclt.nextElement(); int nSpec = 0; // 第二层枚举同样调整泛型声明 final Enumeration<? extends TreeNode> enmDep = fclt.children(); while (enmDep.hasMoreElements()) { final DefaultMutableTreeNode dep = (DefaultMutableTreeNode) enmDep.nextElement(); final Object data = dep.getUserObject(); if (((Dept)data).spec) { ++nSpec; } } System.out.println(fclt + " has " + nSpec + " specdepartments"); } }
方案2:通过通配符中转+抑制警告注解,最小化代码改动
如果你确定业务场景下所有子节点均为DefaultMutableTreeNode类型,可以仅修改报错的两行强转代码,添加注解抑制警告即可:
// 先转成无界通配符的Enumeration中转,再强转目标类型 @SuppressWarnings("unchecked") final Enumeration<DefaultMutableTreeNode> enmFclt = (Enumeration<DefaultMutableTreeNode>) (Enumeration<?>) root.children(); // 第二处报错同理修改 @SuppressWarnings("unchecked") final Enumeration<DefaultMutableTreeNode> enmDep = (Enumeration<DefaultMutableTreeNode>) (Enumeration<?>) fclt.children();
内容的提问来源于stack exchange,提问作者Amwey
相关产品推荐
相关产品推荐

