给出以下代码:
import collection.JavaConversions._
def j(x: java.util.List[java.lang.Integer]): Unit =
// the function body here can be any valid code
println (x)
val a = List(1)
我在调用时遇到类型不匹配错误:
j (seqAsJavaList(a))
以下是REPL的错误
<console>:13: error: type mismatch;
found : List[Int]
required: Seq[Integer]
f (seqAsJavaList(a))
^
但是,我可以在没有错误的情况下调用它:
j(seqAsJavaList(List(1)))
我使用2.11.2。
有人可以向我解释为什么seqAsJavaList的行为有所不同吗?感谢。
为我原来的问题添加更多背景/说明:
我要问的是&#34;为什么seqAsJavaList
在预定义变量a
上操作时的行为与在原位值List(1)
上的行为不同相同的类型?&#34;此外,seqAsJavaList(a)
和seqAsJavaList (List(1))
会返回完全相同的签名java.util.List[Int]
。使用替换模型,可以期望j (seqAsJavaList(a))
和j (seqAsJavaList (List(1)) )
都成功。然而,只有后者才有效。当seqAsJavaList(a)
和seqAsJavaList (List(1))
都是java.util.List[Int]
时,为什么一个用法处理Int
很好而另一个用不处理?
另一个注意事项:
我刚试过collection.JavaConverters
,结果并不理想,但至少是一致的:
// The definitions of j & a are the same as above. I repeat them here to save some page scrolling.
// BTW, instead of f, I use j to indicate it is supposed to be a Java static method.
// I mock it in Scala so that this can be easily run in REPL.
def j ( ls: java.util.List [java.lang.Integer] ): Unit = println (ls)
val a = List( 1 )
// new code here
import collection.JavaConverters._
// Both require the explicit casting to work
j ( a.map (i => i: java.lang.Integer).asJava )
j ( List(1).map (i => i: java.lang.Integer).asJava )
// These fail with the same error.
j( a.asJava )
j( List(1).asJava )
// <console>:12: error: type mismatch;
// found : java.util.List[Int]
// required: java.util.List[Integer]
// j ( List(1).asJava )
// ^
答案 0 :(得分:4)
此处的问题不在于List
,而在于Int
类型。例如,这有效:
scala> j ( seqAsJavaList (a.map(x => x:Integer)) )
[1]
j
期望参数类型为java.util.List [java.lang.Integer]
。但是,您的seqAsJavaList
的返回类型为java.util.List [Int]
。
上面的示例有效,因为现在seqAsJavaList将List [java.lang.Integer]
并返回java.util.List[java.lang.Integer]
。因此它有效。
或者你可以:
scala> implicit def toJavaIntegerList(ls:List[Int]):java.util.List[Integer] = seqAsJavaList(ls.map(x => x:Integer))
scala> j(List(1,2,3))
[1, 2, 3]
<小时/> 解释其原因:
j (seqAsJavaList(List(1)))
这相当于:
scala> val temp:List[Integer] = List(1)
temp: List[Integer] = List(1)
scala> j (seqAsJavaList(temp))
[1]
或更好:j (seqAsJavaList(List(1:Integer)))
类型推断在这里工作。有隐含的功能
implicit def int2Integer(x:Int):java.lang.Integer
在Predef中定义。当您执行j(seqAsJavaList(List(1)))
时,类型推断通过使用转换Int => java.lang.Integer
的隐式函数来预测这可以合法地成功。它看到如果这个隐含用于List
的所有元素,那么调用将合法地成功。因此,List(1)
实际上构建为List[Integer]
而不是List[Int]
通过检查确认
object Temp extends App{
import collection.JavaConversions._
def j(x: java.util.List[java.lang.Integer]): Unit = println (x)
j(seqAsJavaList(List(1)))
}
jatinpuri@jatin:~/Desktop$ scalac -Xprint:typer Temp.scala
[[syntax trees at end of typer]] // Temp.scala
package <empty> {
object Temp extends AnyRef with App {
def <init>(): Temp.type = {
Temp.super.<init>();
()
};
import scala.collection.JavaConversions._;
def j(x: java.util.List[Integer]): Unit = scala.this.Predef.println(x);
Temp.this.j(scala.collection.JavaConversions.seqAsJavaList[Integer](immutable.this.List.apply[Integer](scala.this.Predef.int2Integer(1))))
}
}
注意(immutable.this.List.apply[Integer](scala.this.Predef.int2Integer(1)))
。因此,List(1)
实际上构建为List[Integer]
而不是List[Int]
这在原始情况下不起作用,因为在执行val a = List(1)
时,a
设置为List[Int]
。将其更改为List[Integer]
的唯一方法是将所有内容映射到Integer(因为scala lib中没有隐式可用的转换List[Int] => List[Integer]
)