3

我几乎可以肯定以前有人问过这个问题,但我错过了找到它的正确词。

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 在 a 中处理我的输入Double,但在使用 a 时保留它?有没有办法防止这种行为,而是总是使用 Scala 类型?java.lang.DoubleSeq[Any]scala.DoubleSeq[AnyRef]

4

2 回答 2

7

ScalaDouble与 Java 相对应,double但如果需要,它可能会自动装箱和取消装箱,并且在自动装箱java.lang.Double时会变成这样。在实践中,集合需要对原始变量进行自动装箱。

如果未显式声明类型,则根据分配给它们的值推断您声明的集合类型。问题中两个声明之间的区别在于,Seq(value1,value2,...)类型推断试图找到“最佳”类型,然后根据这种类型(Scala )提出Seq[Double]然后解释value1,依此类推。如果将类型显式声明为,则不会运行类型推断(因为您自己给出了类型),因此不会“强制”将值等解释为固定类型。value2DoubleSeq[Any]value1value2

由于Seq是一个集合,原语是不允许的,必须自动装箱,所以 Javadouble不能适应而java.lang.Double可以。试图隐藏装箱和拆箱Seq[Double]并透明地交换原语和对象的逻辑不起作用。实际上,在 a 中Seq[Any],每个元素可能属于不同的类型,这意味着这种装箱和拆箱在一般情况下不起作用(在您的示例中,与 whichres0(0).getClass是DoubleInteger形成对比)。res2(0).getClass

所以,本质上,如果你不显式声明类型,类型推断就会开始,首先尝试为集合的所有元素找到一个公共类型,然后将所有元素转换为该类型,同时显式指定集合类型参数,没有这样的事情发生,所有值的类型都被解释为“原始”。

于 2013-08-27T20:11:59.153 回答
4

正在发生的是拳击。因为第一个是 a Seq[Any],所以其中的任何原语都将以盒装形式返回。在第二种情况下,因为类型是Seq[Double],对成员的访问将被自动取消装箱(但仍将装箱存储在 中Seq)。

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

于 2013-08-27T20:12:35.477 回答