开发者

Iterating over java List that involves Java generics <?> in Scala

I have an API (from third party java library) that looks like:

public List<?> getByXPath(String xpathExpr)

defined on a class called DomNode

I try this in scala:

node.getByXPath(xpath).toList.foreach {node: DomElement => 

   node.insertBefore(otherNode)   

}

But I get compile error on node.getByXPath. error: "type mismatch; found : (com.html.DomElement) => Unit required: (?0) => ? where type ?0"

If I change it into:

node.getByXPath(xpath).toList.foreach {node => 
开发者_如何学JAVA
   node.insertBefore(otherNode)   

}

then the error goes away but then I get error on node.insertBefore(otherNode) error: "value insertBefore is not a member of ?0"

What is the answer to this problem?


Do this:

node.getByXPath(xpath).toList.foreach { 
    case node: DomElement => node.insertBefore(otherNode)   
}

By using case, you turn it into a pattern matching function. If there's any non-DomElement returned, you'll get an exception -- you can add another case match for the default case to handle it, if necessary.

What you shouldn't do is use asInstanceOf. That throws away any type safety for little to no gain.


You'll have to cast it. ie,

node.getByXPath(xpath).toList.foreach {node => 
   node.asInstanceOf[DomElement].insertBefore(otherNode)   
}

You would have the same issue in Java as the type of List elements is unknown.

(I am assuming every element actually is a DomElement)

EDIT:

Daniel is right, there is a better way to do this. For example, you can throw a much nicer exception (as compared to ClassCastException or MatchError). Eg.

node.getByXPath(xpath).toList.foreach { 
    case node: DomElement => node.insertBefore(otherNode)  
    case _: => throw new Exception("Expecting a DomElement, got a " + node.getClass.getName)   
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜