2011-07-02 79 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