为什么Scala偶尔会回退到Java对象?

Tai*_*aig 3 java scala language-interoperability

我几乎可以肯定以前曾经问过这个问题,但是我错过了找到它的正确的话.

scala> Seq[Any]( 3, 3.4 )
res0: Seq[Any] = List(3, 3.4)

scala> res0( 1 ).getClass
res1: Class[_] = class java.lang.Double

scala> Seq( 3, 3.4 )
res2: Seq[Double] = List(3.0, 3.4)

scala> res2( 1 ).getClass
res3: Class[Double] = double
Run Code Online (Sandbox Code Playgroud)

为什么斯卡拉处理我的Double输入作为java.lang.DoubleSeq[Any],但保持它作为scala.Double一个工作的时候Seq[AnyRef]?有没有办法防止这种行为,而是总是使用Scala类型?

Mic*_*ski 7

Scala Double对应于Java,double但如果需要可能会自动装箱并取消装箱,并且java.lang.Double当它被自动装箱时就会变成.在实践中,集合需要原始变量的自动装箱.

如果未明确声明类型,则声明的集合类型将根据分配给它们的值进行推断.问题中两个声明之间的区别在于,对于Seq(value1,value2,...)类型推理尝试找到"最佳"类型,出现Seq[Double]然后解释value1,value2依此类推(基于此类型)(Scala Double).如果明确声明类型Seq[Any],则不运行类型推理(因为您自己给出了类型),因此值value1" value2等"不会被"强制"解释为固定类型.

由于Seq是一个集合,因此不允许使用原语并且必须自动进行封装,因此Java double无法适应java.lang.Double.试图隐藏装箱和拆箱Seq[Double]以及透明地交换原语和对象的逻辑不起作用.实际上,在一个Seq[Any]中,每个元件可以是不同类型的,这意味着这种装箱和拆箱不能在一般的情况下工作的(在你的例子,res0(0).getClass是一个Integer对比res2(0).getClass这是一个双).

因此,基本上,如果您没有显式声明类型,则类型推理会启动并首先尝试为集合的所有元素查找公共类型,然后将所有元素强制转换为该类型,同时显式指定集合类型参数,不会发生这样的事情,并且所有值的类型都被解释为"原始".