java面试题网站:www.javaoffers.com
Scala中是这样定义下划线 _ 的: _ 代表 ‘’任意‘’
在Scala语言中存在类型推理,就是有的时候你不必指定具体的类型,Scala语言会自动进行推测参数的类型是什么。
比如: var a = "a" 这里Scala会自动推测他为 String类型。
var b = 2 这里Scala 会自动推测他为Int类型
那我们在Scala语言中经常看到使用下滑先 _ ,而且使用的地方很多,比如:
import org.apache._ //导入org.apache下面的任意类
var a: String = _ //代表 a = null , _ 代表任意,给参数初始值的时候 ,Scala 会把 _ 默认推测为 null
map(_) // 代表 集合中的 每一个/任意一个元素对象
a match{
case 'str' => "匹配对象"
case Array(a,b) = > "匹配样板"
case List(_*) => "匹配 任意多个 "
case Int => "匹配类型"
case _ => "匹配任意都成立"
}
有时候下划线 _ 会和 字母变量容易混乱,比如在方法中
var a = Array(1,2,3)
var b = a.map(_*3)
var c = a.map(c*3) //编译不过无法解析
var c2 = a.map(c => c*3)
var b2 = a.map(_ => _*3) //编译不过无法解析
区别: _: String 和 _
第一个下划线 _ 已经不是 任意 了,它是String 类型,
第二个下划线 _ 依然是 任意
这两个下划线完全不同的,第一个是你自己定义的, 第二个是 Scala 默认的,这是要区别开的。
以上区别明白以后再看map 方法:
map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
关键 看 (f: A => B) : 这是一个函数,也就是说 map 方法 让我们传进去一个函数,
明白以后再看上面的例子:
var c2 = a.map(c => c*3) : c => c*3 是一个匿名函数 ,c 的类型由Scala自动推测,当然我们
知道c的类型,我们也可以写成 c: Int = c*3 ,因为Scala有自动推测 所以我们没必要写多余的代码,
var c = a.map(c*3) : c*3 不符合函数格式,所以编译不通过,这只是一个简单的 字母c 乘以 3,没有意义。
那你肯定想 为什么 _ * 3 就可以呢。接着向下看
var b2 = a.map(_ => _*3) :_ => _*3 编译不过无法解析,我们可以吧 _ => _*3 匿名函数 进 行还原
val hs = ( _ : Int ) =>{
_ * 3 // 编译不过无法解析
} 还原以后开始理解他,在参数中 _: Int 是吧 _ 作为了Int 类型,而在函数体中的 下划线 _ Scala依然把他作为 任意型 ,Scala 不会把 参数中的 下划线 _ 映射到 函数体中的下划线,每一个下划线 代表一个单独的个体,这也充分说明 下划线的灵活性,如果Scala把参数中的下划线 _ 映射到函数体中的下划线,那函数体中的每一个下划线都成为了同一个,那Scala中的好多功能就会乱掉,比如在该函数体中 使用模式匹配 :使用 _ 代表任意类型则不能实现了,所有的下划线 _ 只能代表Int 类型,则 scala 把 _ 定义为任意类型就失去了意义,也失去了Scala语言的灵活性,所以每一个 _ 是单独的一个个体 要区别: _: Int 和 _ 的意思,
var b = a.map(_*3) : 因为Scala 不允许 _ => _*3 写,二来 _ 本来就是代表任意型这一点要和一个单独的字母区别,在函数中 直接可以这样使用 _*3 ,去除 _ => 也保证了Scala语言灵活性的初衷,也不干扰 _ 设计为 ‘’任意‘’ 的意义。