2011-07-02 83 views
38

在REPL中,我定義了一個函數。請注意返回類型。Scala字符串與java.lang.String - 類型推斷

scala> def next(i: List[String]) = i.map {"0" + _} ::: i.reverse.map {"1" + _} 
next: (i: List[String])List[java.lang.String] 

如果我指定的返回類型爲字符串

scala> def next(i: List[String]): List[String] = i.map {"0" + _} ::: i.reverse.map {"1" + _} 
next: (i: List[String])List[String] 

爲什麼不同?我也可以指定返回類型爲List [Any],所以我猜String只是java.lang.String的一個包裝類型。這會有什麼實際影響,或者我可以安全地不指定返回類型?

回答

52

這是一個很好的問題!首先,讓我向你保證,你可以安全地指定返回類型。

現在,我們來看看它......是的,當推斷時,Scala推斷java.lang.String,而不僅僅是String。因此,如果您在ScalaDoc中查找「String」,您將找不到任何東西,這似乎表明它不是Scala類。那麼,它必須來自某個地方,不過。

讓我們來考慮Scala默認導入的內容。您可以自己在REPL找到它:

scala> :imports 
1) import java.lang._    (155 types, 160 terms) 
2) import scala._     (801 types, 809 terms) 
3) import scala.Predef._   (16 types, 167 terms, 96 are implicit) 

前兩個包 - 實際上,String可以java.lang找到!那是嗎?讓我們通過實例化該包中的其他東西來檢查:

scala> val s: StringBuffer = new StringBuffer 
s: java.lang.StringBuffer = 

scala> val s: String = new String 
s: String = "" 

所以,看起來並不是這樣。現在,它不能位於scala包中,或者在查找ScalaDoc時發現它。所以我們來看看scala.Predef,它就在那裏!

type String = String 

這意味着String別名java.lang.String(這是以前的進口)。這看起來像一個循環引用,雖然,但如果你檢查source,你會看到它的完整路徑定義:

type String  = java.lang.String 

接下來,你可能要問爲什麼?嗯,我沒有任何想法,但我懷疑是讓這樣一個重要的類少一點依賴於JVM。

+0

字符串文字被推斷爲類型爲java.lang.String的時候,看起來他們同樣可以被推斷爲String類型,這有點奇怪。但很高興知道他們是完全一樣的東西。 –

+0

@Luigi這是因爲文字_are_類型java.lang.String。這裏真的沒有推論 - 它們是文字。 –

+2

也許是我見過的最清晰,最好,理想的答案。令人耳目一新。謝謝丹尼爾 – jbnunn