2010-12-14 17 views
5

在下面的代碼:爲什麼Scala將列表[Any]列入[Long]?

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])) 

這裏是輸出(斯卡拉2.8.1):

0: java.lang.Long 
1: java.lang.Long 
2: java.lang.Long 

爲什麼數字被晉升爲java.lang.Long中?我該如何做到這一點,以便他們保持其AnyVal類型或「盒裝」到相應的AnyRef類型?

回答

13

我想答案是Section 3.5.3 of the language reference

  • 字節弱符合短
  • 短弱符合INT
  • 字符弱符合INT
  • 詮釋弱符合龍
  • Long弱符合Float
  • Float弱符合Double

正因爲如此,斯卡拉推斷短,int和long之間的常見的類型是漫長的,則非長的物體多頭的轉換:

scala> List(0L, 0, 0: Short) 
res1: List[Long] = List(0, 0, 0) 

如果你想使用的整個鏈條弱一致性,嘗試:

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) 

,當然說你想要一個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) 
1
List[Any](0L, 1.asInstanceOf[Int], 2.asInstanceOf[Short]) 
0

這是爲什麼(由PST答案大樓):

scala> val x = List(0L, 1.asInstanceOf[Int], 2.asInstanceOf[Short]) 
x: List[Long] = List(0, 1, 2) 

看來斯卡拉試圖定義列表的類型是可以包含的所有元素的最大對象。例如,

scala> val x = List(0.asInstanceOf[Short], 1.asInstanceOf[Int], 2.asInstanceOf[Short]) 
x: List[Int] = List(0, 1, 2) 

因此,pst建議的解決方法就是答案。

4

類型推斷通過從最具限制性的類型開始(例如, 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) 

List[Long](1L, 2L, 3L)。現在,如果你不喜歡這種行爲,指定列表類型爲AnyValAny

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

編輯:附:如果您指定的是某種類型的常量,則只需說明類型(例如(2: Short))而不是將其轉換爲該類型(例如2.asInstanceOf[Short])。

相關問題