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

为什么Scala偶尔会回到Java对象?,java,scala,language-interoperability,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 res

我几乎可以肯定这个问题以前有人问过,但我找不到合适的词

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

为什么Scala将我的
Double
输入作为
java.lang.Double
处理在
Seq[Any]
中,但在使用
Seq[AnyRef]
时将其保留为
Scala.Double
?有没有办法防止这种行为,而是始终使用Scala类型?

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
是一个
整数,而
res2(0)。getClass
是一个双精度)


因此,从本质上讲,如果不显式声明类型,则类型推断将开始,首先尝试为集合的所有元素找到一个公共类型,然后将所有元素强制转换为该类型,而在显式指定集合类型参数的情况下,不会发生这种情况,并且所有值的类型都被解释为“原始”现在发生的是拳击。因为第一个是
Seq[Any]
,所以其中的任何原语都将以装箱形式返回。在第二种情况下,由于类型为
Seq[Double]
,因此对成员的访问将自动取消装箱(但仍将装箱存储在
Seq
中)


试图获取原语的运行时类必然会导致各种各样的问题。尝试不需要使用
getClass

,但是一个文本,例如
3
,是一个
Int@Taig装箱,因为集合在对象上工作。Scala试图隐藏存在基元类型和对象的事实,但在JVM级别,这种区别确实存在。因为Scala在JVM上运行,所以它受到这个限制。它试图隐藏它,但并不总是可以。JVM没有等价的
AnyVal
,因此在集合中,层次结构看起来只有
java.lang.Integer