Java泛型<! - ? - >以及如何在Scala中处理它?

时间:2011-06-15 09:29:44

标签: scala

我有一个API(来自第三方java库),如下所示:

    public List<?> getByXPath(String xpathExpr)

在名为DomNode

的类上定义

我在scala函数中尝试这个:

1: def removeChild(node: DomNode, xpath: String) {
2:               val lst: List[?] =  node.getByXPath(xpath)
3:      val child: DomNode = lst(0)
4:                child.getParentNode().removeChild(child)
    }

但它不能在scala中编译。我在第2行得到错误。

根据答案,我修改了它,现在它是:

1: def removeChild(node: DomNode, xpath: String) {
2:            val lst = node.getByXPath(xpath)
3:            val child = lst(0).asInstanceOf[DomNode]            
4:            child.getParentNode().removeChild(child)
    }

现在我在第3行得到错误:java.util.List类型的lst [?0]不带参数

我也试过了val lst: List[_] = node.getByXPath(xpath),但这在同一行上给了我错误:

type mismatch;
 found : java.util.List[?0] where type ?0
 required: scala.List[_]

所以我仍然被卡住了。

5 个答案:

答案 0 :(得分:5)

在第3行重新判断你的错误:记住它是一个Java列表,而不是Scala列表,所以试试

val child = lst.get(0).asInstanceOf[DomNode]

答案 1 :(得分:2)

以下是您的代码出了什么问题:

def removeChild(node: DomNode, xpath: String) {
     val lst: List[?] =  node.getByXPath(xpath)
           /* ^^^^^^^ This probably refers to scala.collection.immutable.List,
                      which is a totally different type from the 
                      java.util.List that getByXPath returns.*/
          /* Also, the ? needs to be changed into an _ in Scala */


     val child: DomNode = lst(0)
           /* Two problems here: First, java.util.List won't support indexing 
              with parentheses. Second, you need to typecast the result to get a
              DomNode. */


     child.getParentNode().removeChild(child)
}

以下是更正后的版本:

import scala.collection.JavaConversions._
def removeChild(node:DomNode, xpath:String) {
   val lst:scala.collection.Seq[_] = node.getByXPath(xpath)
       /* triggers an implicit conversion that wraps the Java List in a Scala Seq */

   val child: DomNode = lst(0).asInstanceOf[DomNode]
   child.getParentNode().removeChild(child)
}

(省略类型注释仍然有效 - 而不是在分配val lst时导致转换,当您尝试调用lst(0)时,它会导致转换。)

另一个未转换为Scala Seq的更正版本:

def removeChild(node:DomNode, xpath:String) {
   val lst:java.util.List[_] = node.getByXPath(xpath)
       /* you can remove the type annotation here, but I left it in
          for pedagogical purposes */

   val child: DomNode = lst.get(0).asInstanceOf[DomNode]
   child.getParentNode().removeChild(child)
}

答案 2 :(得分:1)

这应该有效:

val lst: java.util.List[_] =  node.getByXPath(xpath)

答案 3 :(得分:1)

以下对我有用:

val arr = DomNode.getByXPath("foo").toArray
val child = lst(0).asInstanceOf[DomNode]

显然没有将通配符Java列表隐式转换为Scala列表,因此,您创建的val lst属于java.util.list类型,当然没有应用方法。我通过从列表中创建一个Scala数组来解决这个问题。

答案 4 :(得分:0)

这是我的看法:

def removeChild(node: DomNode, xpath: String) {
    // Let type inference do the work for you
    // val lst: List[?] =  node.getByXPath(xpath)
    val lst = node.getByXPath(xpath)

    // Also, do not confuse Java's and Scala's collections
    // val child: DomNode = lst(0)
    val child = lst.get(0)

    // Finally, since you do not have a static guarantee of the type,
    // match on it
    //     child.getParentNode().removeChild(child)
    child match {
        case domNode: DomNode => domNode.getParentNode().removeChild(domNode)
        case _ =>
    }
}