有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法从列表<节点>强制转换为列表<元素>

各位。 我正在练习dom4j和Xpath,但遇到了一个问题

我正试图:

List<Element> conList = (List<Element>)doc.selectNodes("//contact");

但有一个错误:

Cannot cast from List<Node> to List<Element>

代码在教学视频中似乎运行良好, 但在我的电脑里不工作

这是一种非法的行动吗? 我能用其他方法解决这个问题吗? 谢谢


共 (2) 个答案

  1. # 1 楼答案

    这是一个令人沮丧的问题,因为您知道(从XPath表达式的语义来看),列表中的项都是Element的实例,但无法告诉Java编译器这一点。如果DOM4J的设计者想得更仔细一点,他们会将结果声明为List<? extends Node>,这会给您带来更大的灵活性(尽管强制转换仍然会给您编译器警告)。这也是令人沮丧的,因为该规则的原因都是关于向列表中添加不适当项的危险,而您真正想要的是一个不应该出现问题的不可变列表(尽管它仍然存在,因为泛型并不专门处理不可变集合)

    @MagnusLutz给出的干净解决方案可以满足编译器的要求,但代价很高——它需要复制列表

    在Saxon9.9中,我设计了一个新的API,它可以很好地处理泛型,并且可以与DOM4J一起使用,所以请尝试一下。对于这样的简单情况,它还避免了编译/解释XPath表达式的成本。但是(遗憾的是)它并没有解决泛型的潜在限制,特别是在XPath表达式之类的构造中,XPath编译器可用的类型信息不能与Java编译器共享

    你到底想对这些元素做什么?如果我需要将列表传递给需要List<Element>的方法,那么我可能会使用@MagnusLutz的解决方案。如果我只想处理元素,我会这样做

    for (Node n : doc.selectNodes("//contact")) {
       Element e = (Element)n;
       ...
    }
    
  2. # 2 楼答案

    您不能简单地用这种方式强制转换具有具体参数的基于泛型的对象

    实现目标的一个好方法是:

    List<Element> conList = doc.selectNodes("//contact")
    .stream()
    .map(node->(Element)node)
    .collect(Collectors.toList());
    

    请注意,对于不知道列表元素是否实际上是目标类或接口实例的一般情况,您可能希望通过筛选来断言这一点

    List<Element> conList = doc.selectNodes("//contact")
    .stream()
    .filter(node->node instanceof Element)
    .map(node->(Element)node)
    .collect(Collectors.toList());