我试图定义一个结构类型,该结构类型与具有泛型类型的实例匹配。像下面的示例代码一样:
class ExampleTest extends FlatSpec with Matchers {
def add[T](container: {def add(s: T): Boolean})(element: T): Unit = {
container.add(element)
}
val set = new java.util.HashSet[String]()
add(set)("3")
set.contains("3") shouldEqual true
val list = new java.util.LinkedList[String]()
add(list)("3")
list.contains("3") shouldEqual true
}
但出现编译错误:
Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
def add[T](container: {def add(s: T): Boolean})(element: T): Unit = {
当我摆脱方法中的泛型类型并编写如下代码时:
class ExampleTest extends FlatSpec with Matchers {
def add(container: {def add(s: String): Boolean}): Unit = {
container.add("3")
}
val set = new java.util.HashSet[String]()
add(set)
set.contains("3") shouldEqual true
val list = new java.util.LinkedList[String]()
add(list)
list.contains("3") shouldEqual true
}
它可以编译,但是出现运行时异常:
java.lang.NoSuchMethodException: java.util.HashSet.add(java.lang.String)
我的问题是: 如何正确定义结构类型,使其可以与Java集合一起使用?
请注意,它不能用Scala集合替换它们(它将与Java库一起使用)。
答案 0 :(得分:1)
尝试
import scala.language.reflectiveCalls
def add[T](container: {def add(s: Any): Boolean})(element: T): Unit = {
container.add(element)
}
val set = new java.util.HashSet[String]()
add(set.asInstanceOf[{def add(s: Any): Boolean}])("3")
set.contains("3") shouldEqual true
val list = new java.util.LinkedList[String]()
add(list.asInstanceOf[{def add(s: Any): Boolean}])("3")
list.contains("3") shouldEqual true
java.util.HashSet#add
(实际上是java.util.AbstractCollection#add
)和java.util.LinkedList#add
的签名是
boolean add(E e)
对结构类型的反射调用在运行时解决。在运行时,由于类型擦除,泛型E
只是Any
(又名Object
)。