无法从 List<Node> 转换为 List<Element>
Cannot cast from List<Node> to List<Element>
各位。
我正在练习 dom4j 和 Xpath,但遇到了一个问题。
我正在尝试:
List<Element> conList = (List<Element>)doc.selectNodes("//contact");
但出现错误:
Cannot cast from List<Node> to List<Element>
该代码在教学视频中似乎运行良好,
但在我的电脑上不起作用。
是否属于非法操作?
我可以通过任何其他方式解决问题吗?
谢谢
您不能简单地以这种方式转换具有具体参数的基于泛型的对象。
一个很好的 java8 实现目标的方法是:
List<Element> conList = doc.selectNodes("//contact")
.stream()
.map(node->(Element)node)
.collect(Collectors.toList());
请注意,对于您不知道列表元素是否实际上是目标 class 或接口的实例的一般情况,您可能希望通过过滤
来断言
List<Element> conList = doc.selectNodes("//contact")
.stream()
.filter(node->node instanceof Element)
.map(node->(Element)node)
.collect(Collectors.toList());
这是一个令人沮丧的问题,因为您知道(从 XPath 表达式的语义)列表中的项目都是 Element
的实例,但是无法告诉 Java编译器那个。如果 DOM4J 的设计者考虑得更仔细一些,他们会将结果声明为 List<? extends Node>
,这会给您更多的灵活性(尽管转换仍然会给您编译器警告)。这也令人沮丧,因为该规则的原因完全是关于将不适当的项目添加到列表中的危险,而您真正想要的是一个不应该出现问题的不可变列表(尽管它仍然会出现,因为泛型不会处理特别是不可变集合)。
@MagnusLutz 给出的干净解决方案将满足编译器的要求,但它很昂贵 - 它涉及复制列表。
在 Saxon 9.9 中,我设计了一个新的 API,它试图很好地处理泛型,并且它可以与 DOM4J 一起使用,所以请尝试一下。对于像这样的简单情况,它还避免了 compiling/interpreting XPath 表达式的成本。但是(遗憾的是)它并没有解决泛型的潜在局限性,尤其是与像 XPath 表达式这样的结构有关,其中 XPath 编译器可用的类型信息无法与 Java 编译器共享。
你到底想用这些元素做什么?如果我需要将列表传递给需要 List<Element>
的方法,那么我可能会使用@MagnusLutz 的解决方案。如果我只是想处理元素,我会做
for (Node n : doc.selectNodes("//contact")) {
Element e = (Element)n;
...
}
各位。 我正在练习 dom4j 和 Xpath,但遇到了一个问题。
我正在尝试:
List<Element> conList = (List<Element>)doc.selectNodes("//contact");
但出现错误:
Cannot cast from List<Node> to List<Element>
该代码在教学视频中似乎运行良好, 但在我的电脑上不起作用。
是否属于非法操作? 我可以通过任何其他方式解决问题吗? 谢谢
您不能简单地以这种方式转换具有具体参数的基于泛型的对象。
一个很好的 java8 实现目标的方法是:
List<Element> conList = doc.selectNodes("//contact")
.stream()
.map(node->(Element)node)
.collect(Collectors.toList());
请注意,对于您不知道列表元素是否实际上是目标 class 或接口的实例的一般情况,您可能希望通过过滤
来断言List<Element> conList = doc.selectNodes("//contact")
.stream()
.filter(node->node instanceof Element)
.map(node->(Element)node)
.collect(Collectors.toList());
这是一个令人沮丧的问题,因为您知道(从 XPath 表达式的语义)列表中的项目都是 Element
的实例,但是无法告诉 Java编译器那个。如果 DOM4J 的设计者考虑得更仔细一些,他们会将结果声明为 List<? extends Node>
,这会给您更多的灵活性(尽管转换仍然会给您编译器警告)。这也令人沮丧,因为该规则的原因完全是关于将不适当的项目添加到列表中的危险,而您真正想要的是一个不应该出现问题的不可变列表(尽管它仍然会出现,因为泛型不会处理特别是不可变集合)。
@MagnusLutz 给出的干净解决方案将满足编译器的要求,但它很昂贵 - 它涉及复制列表。
在 Saxon 9.9 中,我设计了一个新的 API,它试图很好地处理泛型,并且它可以与 DOM4J 一起使用,所以请尝试一下。对于像这样的简单情况,它还避免了 compiling/interpreting XPath 表达式的成本。但是(遗憾的是)它并没有解决泛型的潜在局限性,尤其是与像 XPath 表达式这样的结构有关,其中 XPath 编译器可用的类型信息无法与 Java 编译器共享。
你到底想用这些元素做什么?如果我需要将列表传递给需要 List<Element>
的方法,那么我可能会使用@MagnusLutz 的解决方案。如果我只是想处理元素,我会做
for (Node n : doc.selectNodes("//contact")) {
Element e = (Element)n;
...
}