在 Scala编程 中,给出以下示例以说明如何使用通配符引用Java类。方法javaSet2ScalaSet
采用类型T.通常,您始终可以显式提供参数化类型。但在(new Wild).contents
存在的情况下,普通类型参数是不可接受的。
在没有类型参数的情况下调用javaSet2ScalaSet
时,编译器能够执行一些魔法并推断出适当的参数。查看编译器使用scalac -Xprint:typer提供的内容,表明它为T赋值为?0。无法手动提供。
这是一个特殊情况,只适用于推断类型,还是有某种方式明确提供类型?
// This is a Java class with wildcards
public class Wild {
Collection<?> contents() {
Collection<String> stuff = new Vector<String>();
stuff.add("a");
stuff.add("b");
stuff.add("see");
return stuff;
}
}
import scala.collection.mutable.Set
import java.util.Collection
abstract class SetAndType {
type Elem
val set: Set[Elem]
}
def javaSet2ScalaSet[T](jset: Collection[T]): SetAndType = {
val sset = Set.empty[T] // now T can be named!
val iter = jset.iterator
while (iter.hasNext)
sset += iter.next()
return new SetAndType {
type Elem = T
val set = sset
}
}
val setAndType = javaSet2ScalaSet((new Wild).contents)
答案 0 :(得分:1)
这只是一个句法限制,而不是固有的限制。以下是您可以声明的方式:
def javaSet2ScalaSet[C <: Collection[T] forSome { type T }](jset: C): SetAndType = {
val sset = Set.empty[T forSome { type T }]
val iter = jset.iterator
while (iter.hasNext)
sset += iter.next()
return new SetAndType {
type Elem = T forSome { type T }
val set = sset
}
}
答案 1 :(得分:0)
(Q1)&gt;&gt;这是一种特殊情况,仅适用于推断类型。 &LT;&LT;
编译器不会将Java集合的类型推断为Collection类型。它只知道它是一个包含某种类型元素的集合。
(Q2)&gt;&gt;或者有没有办法明确提供类型? &LT;&LT;
没有。不提供存在类型。它不是一个被绑定的自由变量(因为它已被绑定)。
以这种方式看待它:假设你能够提供类型。然后,您希望编译器检查提供的类型是否与Java集合中的元素类型匹配。但编译器无法确定这一点。所以万一他们不匹配,你无论如何只能在运行时找到。
如果您想告诉Scala编译器您知道java集合中的元素是String类型(例如,您想调用x.length),那么您可以使用asInstanceOf [String]强制转换元素。但这不会引入类型安全。您将再次仅在运行时发现它是否不正确。