为什么Scala将List [Any]列为[Long]?

Ral*_*lph 5 scala primitive-types

在以下代码中:

def test(list: List[Any]): Unit = {
  list.foreach {
    v =>
    v match {
      case r: AnyRef => println(r + ": " + r.getClass.getName)
      case d: Double => println(d + ": Double")
      case f: Float=> println(f + ": Float")
      case b: Byte => println(b + ": Byte")
      case c: Char => println(c + ": Char")
      case s: Short => println(s + ": Short")
      case i: Int => println(i + ": Int")
      case l: Long=> println(l + ": Long")
      case b: Boolean => println(b + ": Boolean")
      case _ => throw new IllegalArgumentException("Unknown type: " + v)
    }
  }
}

test(List(0L, 1.asInstanceOf[Int], 2.asInstanceOf[Short]))
Run Code Online (Sandbox Code Playgroud)

这是输出(Scala 2.8.1):

0: java.lang.Long
1: java.lang.Long
2: java.lang.Long
Run Code Online (Sandbox Code Playgroud)

为什么数字被提升为java.lang.Long?我怎么能这样做,以便他们保持他们的AnyVal类型或"盒装"到等效AnyRef类型?

Ste*_*eve 13

我认为答案在语言参考的第3.5.3节中:

  • 字节弱于符合Short
  • 短暂的弱点符合Int
  • Char弱于符合Int
  • Int弱于Long
  • 长弱与Float一致
  • Float弱地符合Double

因此,Scala推断Short,Int和Long之间的公共类型是Long,然后将非Long对象转换为Longs:

scala> List(0L, 0, 0: Short) 
res1: List[Long] = List(0, 0, 0)
Run Code Online (Sandbox Code Playgroud)

如果您想使用整个弱一致性链,请尝试:

scala> List(0: Byte, 1: Short, 'c', 3, 4L, 5.0f, 6.0)
res2: List[Double] = List(0.0, 1.0, 99.0, 3.0, 4.0, 5.0, 6.0)
Run Code Online (Sandbox Code Playgroud)

而且,当然要说你想要一个List[Any],只需加入[Any]你的电话List:

scala> List[Any](0: Byte, 1: Short, 'c', 3, 4L, 5.0f, 6.0)
res11: List[Any] = List(0, 1, c, 3, 4, 5.0, 6.0)
Run Code Online (Sandbox Code Playgroud)


Rex*_*err 5

类型推断的工作原理是从最严格的类型(例如Nothing)开始,然后扩展直到一种类型可以包含所有内容。对于数值,这意味着从Int到扩大Long。但是现在,由于调用是有效的,List[Long](ls: Long*)所有数值都被提前提升。

因此,例如,所有这些都给出了相同的列表:

List(1, 2: Byte, 3: Long)
List(1L, 2, 3: Short)
List(1: Byte, 2: Long, 3: Byte)
Run Code Online (Sandbox Code Playgroud)

即一个List[Long](1L, 2L, 3L)。现在,如果您不喜欢这种行为,请将列表的类型指定为AnyValor Any

List[Any](1, 2: Byte, 3: Long)
List.head.asInstanceOf[AnyRef].getClass   // java.lang.Integer
Run Code Online (Sandbox Code Playgroud)

编辑: PS 如果您指定某个类型的常量,您应该只说明类型(例如(2: Short))而不是将其转换为该类型(例如2.asInstanceOf[Short])。