java-编译器忽略的泛型类型

最近我偶然发现了一个看起来不合逻辑的泛型的边缘情况。

我有一个简单的界面,它返回一个孩子的列表:

public interface INode<C extends INode> {

    List<C> getChildren();

}

我希望如果 INode 类型在没有定义 C 类型的情况下被引用,C 类型将被编译器推断为 INode。换句话说,在下面的代码中:

    public void retrieveChildren(INode node)  {

        var children = node.getChildren();

    }

儿童将被推断为List<INode>类型。相反,它只是普通的 List。

值得注意的是,类型推断在 INode 方法返回单个元素的情况下按预期工作,因此当此接口时:

public interface INode<C extends INode> {
    
    C getFirstChild();
    
}

用于以下方法:

    public void retrieveFirstChild(INode node)  {

        var firstChild = node.getFirstChild();

    }

firstChild 被正确地推断为 INode。

jdk 有这样工作的理由吗?另外,是否有一种干净的方法可以为返回的列表强制使用 C 类型?

非常感谢。

回答

儿童将被推断为 List< INode> 类型。相反,它只是普通的 List。

一旦你使用原始类型,它就会感染一切。INode具有 typeargs,并且在您的签名 ( retrieveFirstChild) 中,您使用它原始,这意味着涉及任何泛型与该变量的所有交互也是原始的。

解决方案是永远不要使用 raw(编译器警告,你应该注意这些警告!):

public void retrieveFirstChild(INode<?> node) {
 // note the <?> up there!
    var firstChild = node.getFirstChild();
}

现在 firstChild 的类型是INode,正如预期的那样。


以上是java-编译器忽略的泛型类型的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>