類型檢查和類型轉換在每一個語言裏面都有對應實現,好比Java
中的instanceof
和 isInstance
,固然Scala語言也有,可是相對於其餘語言,Scala
爲了簡化開發,產生了強大的模式匹配,其原理和Java
中的switch-case
很相似,可是其匹配能力更強,不單單能夠匹配值,匹配類型,也能夠進行類匹配,還能夠進行前綴類匹配,並且在Spark
源碼中大量使用了模式匹配,另外的就是隱式轉換,在另一篇文章講解,本文從類型檢查和類型轉換入手,引入Scala
常見的幾種模式匹配及其使用。編程
要測試某個對象是否屬於某個給定的類,能夠用isInstanceOf
方法。若是測試成功,能夠用asInstanceOf
方法進行類
型轉換。數組
if(p.isInstanceOf[Employee]){ //s的類型轉換爲Employee val s = p.asInstanceOf[Employee] }
類型轉換主要有下面幾個點要注意的:app
若是p指向的是Employee
類及其子類的對象,則p.isInstanceOf[Employee]
將會成功。框架
若是p是null,則p.isInstanceOf[Employee]
將返回false,且p.asInstanceOf[Employee]
將返回null。dom
若是p不是一個Employee
,則p.asInstanceOf[Employee]
將拋出異常。分佈式
若是想要測試p指向的是一個Employee
對象但又不是其子類,能夠用:if(p.getClass == classOf[Employee])
classOf
方法定義在scala.Predef
對象中,所以會被自動引入。不過,與類型檢查和轉換相比,模式匹配一般是更好的選擇。函數
p match{ //將s做爲Employee處理 case s: Employee => ... //p不是Employee的狀況 case _ => .... }
Scala 中的模式匹配總結來講支持下面幾種匹配:值匹配,類型匹配,集合元素,元組匹配,有值或者無值匹配,下面從代碼角度來看看這幾種匹配如何使用,首先模式匹配的語法結構以下:oop
變量 match { case xx => 代碼 }
和Java
的不一樣點,不須要指定break
,即有break
的效果,使用佔位符_
來表明默認值,另外match
和 if
同樣有返回值。測試
值匹配,即相似Java
中的整型,字符或者,字符串匹配。可是其之處守衛式匹配(能夠理解爲默認狀況下的條件匹配)大數據
//字符匹配 def main(args: Array[String]): Unit = { val charStr = '6' charStr match { case '+' => println("匹配上了加號") case '-' => println("匹配上了減號") case '*' => println("匹配上了乘號") case '/' => println("匹配上了除號") //注意:不知足以上全部狀況,就執行下面的代碼 case _ => println("都沒有匹配上,我是默認值") } } //字符串匹配 def main(args: Array[String]): Unit = { val arr = Array("hadoop", "zookeeper", "spark") val name = arr(Random.nextInt(arr.length)) name match { case "hadoop" => println("大數據分佈式存儲和計算框架...") case "zookeeper" => println("大數據分佈式協調服務框架...") case "spark" => println("大數據分佈式內存計算框架...") case _ => println("我不認識你...") } } //守衛式匹配 def main(args: Array[String]): Unit = { //守衛式 val character = '*' val num = character match { case '+' => 1 case '-' => 2 case _ if character.equals('*') => 3 case _ => 4 } println(character + " " + num) }
類型匹配是相對於Java
來講的優點點,Java
是作不到的,匹配格式以下:case 變量名:類型
,變量名能夠用_
來代替
//類型匹配 def typeMathc (x: Any) = { x match { case _: String => println("字符串") case _: Int => println("整形") case _: Array[Int] => println("正星星數組") case _ => println("nothing") } }
不一樣於類型匹配的是,類型匹配只能匹配到整個大的類型,而這種匹配能夠匹配相似像某類,可是又能夠限制匹配類的部分元素
//數組模式匹配 def arrayMatch(x: Array[Int]) = { x match { case Array(1,x,y) => println(x + ":" + y) case Array(1) => println("only 1 ....") case Array(1,_*) => println("1 開頭的") case _ => println("nothing....") } } //list模式匹配 def listMatch() = { val list = List(3, -1) //對List列表進行模式匹配,與Array相似,可是須要使用List特有的::操做符 //構造List列表的兩個基本單位是Nil和::,Nil表示爲一個空列表 //tail返回一個除了第一元素以外的其餘元素的列表 //分別匹配:帶有指定個數元素的列表、帶有指定元素的列表、以某元素開頭的列表 list match { case x :: y :: Nil => println(s"x: $x y: $y") case 0 :: Nil => println("only 0") case 1 :: _ => println("1 ...") case _ => println("something else") } } //元組匹配 def tupleMatch() = { val tuple = (5, 3, 7) tuple match { case (1, x, y) => println(s"1, $x, $y") case (_, z, 5) => println(z) case _ => println("else") } }
當數組內沒有寫值,下面幾種匹配等效,任意參數等於徹底類型匹配
case Array(_*) => println("*") case _: Array[Int] => println("整個數組")
case class樣例類是Scala中特殊的類。當聲明樣例類時,如下事情會自動發生:
主構造函數接收的參數一般不須要顯式使用var或val修飾,Scala會自動使用val修飾
自動爲樣例類定義了伴生對象,並提供apply方法,不用new關鍵字就可以構造出相應的對象
將生成toString、equals、hashCode和copy方法,除非顯示的給出這些方法的定義
繼承了Product和Serializable這兩個特質,也就是說樣例類可序列化和可應用Product的方法
case class是多例的,後面要跟構造參數,case object是單例的。
此外,case class樣例類中能夠添加方法和字段,而且可用於模式匹配。怎麼理解樣例類的模式匹配呢,在使用動態綁定時候,從樣例類的繼承中能夠判斷,某個對象是否屬於某個子類對象,而面向父類的接口,能夠簡化編程的設計。跟第一部分說到的isInstanceOf
相似,同時,樣例類能夠接受輸入參數進行對應的子類操做。
class Amount //定義樣例類Dollar,繼承Amount父類 case class Dollar(value: Double) extends Amount //定義樣例類Currency,繼承Amount父類 case class Currency(value: Double, unit: String) extends Amount //定義樣例對象Nothing,繼承Amount父類 case object Nothing extends Amount object CaseClassDemo { def main(args: Array[String]): Unit = { judgeIdentity(Dollar(10.0)) judgeIdentity(Currency(20.2,"100")) judgeIdentity(Nothing) } //自定義方法,模式匹配判斷amt類型 def judgeIdentity(amt: Amount): Unit = { amt match { case Dollar(value) => println(s"$value") case Currency(value, unit) => println(s"Oh noes,I got $unit") case _: Currency => println(s"Oh noes,I go") case Nothing => println("Oh,GOD!") } } }
Scala Option
選項類型用來表示一個值是可選的,有值或無值。
Option[T]
是一個類型爲 T 的可選值的容器,能夠經過get()
函數獲取Option
的值。若是值存在,Option[T]
就是一個
Some
。若是不存在,Option[T]
就是對象 None
。
Option
一般與模式匹配結合使用,用於判斷某個變量是有值仍是無值,下面以Map
的自帶返回值Option
來看看這種匹配。
val grades = Map("jacky" -> 90, "tom" -> 80, "jarry" -> 95) def getGrade(name: String): Unit = { val grade: Option[Int] = grades.get(name) grade match { case Some(grade) => println("成績:" + grade) case None => println("沒有此人成績!") } } def main(args: Array[String]): Unit = { getGrade("jacky") getGrade("張三") }
Scala
中模式匹配,是用來簡化代碼,實現更多強大的不肯定或肯定的匹配,同時還能夠自定義模式匹配,其匹配時候自動利用了apply
和 unapply
方法。
吳邪,小三爺,混跡於後臺,大數據,人工智能領域的小菜鳥。
更多請關注