Scala 中的 _
是一个功能强大且灵活的语法糖,在不同的场景中有不同 的含义,总结记录一下目前碰到的 _
的含义
模块导入 Scala 中导入 package 时, _
类似于 Java导包的 *
1 2 3 4 5 6 7 8 9 import org.apache.spark.sql._import org.apache.spark.sql.SparkSession ._import org.apache.spark.sql.{SparkSession => CustomSparkSesion , _}import org.apache.spark.sql.{SparkSession => _, _}
初始化赋值 _
用于一个类的初始化赋值。 注意, 如果成员声明在构造器参数列表时, 则不能使用 _
赋值。
1 2 3 4 5 case class Converter (beforeConverted:String ) { var afterConverted:String = _ }
模式匹配 Scala中的模式匹配和 C/C++
或者 Java
中的 switch-case
语句类似。 在 Scala
中的模式匹配中, 下划线 _ 是匹配任意内容的通配符。最基本的用法中, _
相当于 switch
中的 default
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 abstract class Storage ;case class MemoryOnly ( ) extends Storage ;case class DiskOnly ( ) extends Storage ;case class MemoryWithSerialization ( ) extends Storage ;case class DiskWithSerialization ( ) extends Storage ;def getStorageType (storage: Storage ): String = storage match { case memoryOnly: MemoryOnly => return "memoryOnly" case diskOnly: DiskOnly => return "diskOnly" case _ => return "serialization" }
更高阶的用法中, _
可以嵌套使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 abstract class SQLConnector ;case class MySQLConnector (ip: String , port: Int , userName: String , password: String ) extends SQLConnector case class HBaseConnector (zookeeperConnectString: String ) extends SQLConnector case class RedisConnector (redisHost: String , auth: String ) extends SQLConnector def getConnectorMessage (sqlConnector: SQLConnector ): String = sqlConnector match { case MySQLConnector (ip, _, userName, _) => s"We want to connect mysql in ip:$ip with userName:$userName " case HBaseConnector (zookeeperConnectString) => s"We want to connect hbase under zookeeper server(s):$zookeeperConnectString " case RedisConnector (redisHost, _) => s"We want to connect redis in ip:$redisHost " }
省略匿名表达式参数 Scala
和 Python
, C++
等语言一样,也有匿名函数的设定。 _
可以用来作为匿名函数的参数占位符, 但是对于每一个参数, 只能用 _
占位一次。 例如,在 Scala 中, 1 + _
相当于 Python 中的 lambda x : x + 1
。
尤其要注意的是, 在Scala中, _+_
表示匿名函数接受2个参数, 函数返回值是两个参数之和,除此之外, Scala 代码中的 print(_)
相当于 x => print(x)
:
1 2 3 Range (0 , 100 ).foreach(print(_))Range (0 , 100 ).reduce(_ + _)
传递不定参数 Scala不支持将数组直接传入到一个不定参参数中, 此时使用 _*
符号进行转化
1 2 3 4 5 def sum (ints:Int *):Int = ints.sumval numbers = Range (1 , 200 )sum(numbers:_*)
防止函数意外调用 在 Scala 中,函数是一等公民,和普通变量一样可以赋值。但由于在 Scala 中函数调用时可省略括号,如果你打算将一个函数赋值给一个新的变量,则函数可能会被意外地调用而后将函数的返回值赋值。这种时候,我们需要在函数名之后加上 _
来阻止函数调用。
1 2 3 4 5 6 7 class CertainService { def processService (): Unit = { } val serviceHandler = processService _ }
忽略类型参数 _
可以用做忽略类型参数, 和 Java 中的 <?>
类似:
1 2 3 4 5 def getLengthOfList (rawList: Option [List [_]]):Int = { rawList match { case Some (list: List [_]) => list.length case None => 0 }
Trait中的自身引用 若希望特质仅被某个满足条件的类所使用,就可以自身引用做限定,写法举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 trait Tool { _ : Computer => override def activate (): Unit = { println("use tools." ) } } class Computer { def activate () : Unit = println("Start" ) }
区分getter和setter 在 Scala 中,函数是一等公民,和普通变量一样可以赋值。但由于在 Scala 中函数调用时可省略括号,如果你打算将一个函数赋值给一个新的变量,则函数可能会被意外地调用而后将函数的返回值赋值。这种时候,我们需要在函数名之后加上 _
来阻止函数调用
1 2 3 4 5 6 7 8 9 class CertainService { private var item:Int = -1 def display : Int = item def display_ = (record:Int ) => { require(record > 0 ) item = record } }