一、scala的數據類型
1,概述:
1)scala與java有着相同的數據類型,在scala中數據類型都是對象,也就是說是scala中沒有java的原生類型 2)scala數據類型分爲兩大類AnyVal(值類型)和AnyRef(引用類型),注意:不管是AnyVal還是AnyRef都是對象。 3)相對於java的類型系統,scala要複雜些!也正是這複雜多變的類型系統才能讓面向對象編程和函數式編程完美的融合在一起
2,數據類型體系一覽圖:
1)scala中有一個根類型Any,它是所有類型的父類 2)scala中一切皆對象,分爲兩類Anyval(值引用)和AnyRef(對象引用),它們都是Any子類 3)Null類型是scala的特別類型,它只有一個值null,它是bottom class是所有AnyRef類型的子類 4)Nothing類型也是bottom class,它是所有類的子類,在開發中通常可以將Nothing類型的值返回給任意變量或者函數,這裏拋出異常使用很多
5)在scala中仍然遵守,低精度的值向高精度的值自動轉換(implicit conversion)隱式轉換。
3,Unit類型、Null類型和Nothing類型
1)Null類只有一個實例對象null,類似於Java中的null引用。null可以賦值給任意引用類型(AnyRef),但是不能賦值給值類型(AnyVal:比如Int,Float,Char,Boolean,Long,Double,Byte和Short) 2)Unit類型用來標識過程,也就是沒有明確返回值的函數。由此可見,Unit類似於Java裏的void。Unit只有一個實例{},這個實例也沒有實質性的意義。 3)Nothing類型是Scala類層級的最低端,它是任何其他類型的子類型。當一個函數,我們確定沒有正常的返回值時,可以用Nothing來指定返回類型,這樣我們可以把返回的值(異常)賦給其他的函數或者變量
二、Scala的邏輯運算
1,if
if的邏輯運算與java基本類似,但是scala中if函數有返回值爲(方法體的返回值)
2,for
0.until(10)等同於0 until 10 等同於Range(0,10) for(i<-0 until 10){ } 其中until爲左閉右; to爲左閉右閉
for循環中的break的使用
import scala.util.control.Breaks._ breakable{ for (i<- 0 to 10) { if (i==5){ break //break並非關鍵字而是Breaks中的break()方法,由於是無參函數可省略小括號直接調用 } println(s"${i}") } }
三、函數式編程
1,定義
def 函數名 ([參數名:參數類型],...)[[:返回值類型=]]{ 語句... return 返回值 }
a)函數聲明關鍵字爲def(definition)
b)[參數名:參數類型],... :表示函數的輸入(就是參數列表),可以沒有。如果有,多個參數使用逗號隔開
c)函數中的語句:表示爲了實現某一功能代碼塊
d)函數可以有返回值,也可以沒有
形式1: :返回值類型= 形式2: = 表示返回值類型不確定,使用類型推導完成 形式3: 空 表示沒有返回值,return不生效 等同於`:Unit=`
e)如果沒有return,默認執行最後一行的結果爲返回值
2,函數的參數和返回值
在scala中無論是值引用、對象引用還是函數都能作爲函數的輸入參數和返回值類型
a)函數作爲參數
def f1(f: (Int) => Int) = { f(10) //調用傳遞進入的函數 } println(f1((i) => i + 10)) //將匿名函數(i) => i + 10作爲參數 //println(f1(_ + 10)) //簡化效果
b)函數作爲返回值
def f3(a:Int) ={ println(a+10) } def f2() ={ f3 _ //返回函數f3不調用 } f2()(20) //函數的柯里化
c)函數的入參
//默認參數 def test(a:Int,b:Int=10) =a+b println(test(12)) //結果22,b的默認值爲10 也可以指定爲test(a=12)帶名參數 //可變參 def test1(arr: Int*) = { var sum: Int = 0 for (i <- arr) { sum += i } sum } println(test1(1, 2,3)) //結果6
3,函數/方法注意事項和細節討論
1)函數的形參列表可以是多個, 如果函數沒有形參,調用時 可以不帶() 2)形參列表和返回值列表的數據類型可以是值類型和引用類型。 3)Scala中的函數可以根據函數體最後一行代碼自行推斷函數返回值類型。那麼在這種情況下,return關鍵字可以省略 4)因爲Scala可以自行推斷,所以在省略return關鍵字的場合,返回值類型也可以省略 5)如果函數明確使用return關鍵字,那麼函數返回就不能使用自行推斷了,這時要明確寫成 : 返回類型 = ,當然如果你什麼都不寫,即使有return 返回值爲() 6)如果函數明確聲明無返回值(聲明Unit),那麼函數體中即使使用return關鍵字也不會有返回值 7)如果明確函數無返回值或不確定返回值類型,那麼返回值類型可以省略(或聲明爲Any) 8)Scala語法中任何的語法結構都可以嵌套其他語法結構(靈活),即:函數/方法中可以再聲明/定義函數/方法,類中可以再聲明類 9)Scala函數的形參,在聲明參數時,直接賦初始值(默認值),這時調用函數時,如果沒有指定實參,則會使用默認值。如果指定了實參,則實參會覆蓋默認值 10)如果存在多個參數,每一個參數都可以設定默認值,那麼這個時候,傳遞的參數到底是覆蓋默認值,還是賦值給沒有默認值的參數,就不確定了(默認按照聲明順序[從左到右])。在這種情況下,可以採用帶名參數11)scala 函數的形參默認是val的,因此不能在函數中進行修改. 12)遞歸函數未執行之前是無法推斷出來結果類型,在使用時必須有明確的返回值類型 13)Scala函數支持可變參數
4,惰性函數
lazy val res = sum(1, 2) println("-----------------------") println("res=" + res) //當需要使用到res時,就會真正的開始計算 //將來這個計算方法是非常耗費運力 def sum(n1: Int, n2: Int): Int = { println("sum 被調用..") n1 + n2 }
1)lazy 不能修飾 var 類型的變量
2)不但是在調用函數時,加了lazy ,會導致函數的執行被推遲,我們在聲明一個變量時,如果給聲明瞭 lazy ,那麼變量值得分配也會推遲。 比如 lazy val i = 10
5,異常
a)scala中的異常處理代碼
//scala中去掉所謂的checked(編譯) 異常 //設計者認爲,如果程序員編程時,認爲某段代碼可疑,就直接try並處理 //說明 //1. 如果代碼可疑,使用try進行處理 //2. 在catch中,可以有多個case ,對可能的異常進行匹配 //3. case ex: Exception => println("異常信息=" + ex.getMessage) // (1) case 是一個關鍵字 // (2) ex: Exception 異常的種類 // (3) => 表明後的代碼是對異常進行處理,如果處理的代碼有多條語句可以{}擴起 //4. 在scala中把範圍小的異常放在後面,語法不會報錯,但是不推薦 //5. 如果捕獲異常,代碼即使出現異常,程序也不會崩潰。 try { var res = 10 / 0 } catch { case ex: ArithmeticException => { println("算術異常=" + ex.getMessage) println("111") } case ex: Exception => println("異常信息=" + ex.getMessage) } finally { println("finaly的代碼...") } println("程序繼續....")
b)異常處理小結
1)我們將可疑代碼封裝在try塊中。 在try塊之後使用了一個catch處理程序來捕獲異常。如果發生任何異常,catch處理程序將處理它,程序將不會異常終止。 2)Scala的異常的工作機制和Java一樣,但是Scala沒有“checked(編譯期)”異常,即Scala沒有編譯異常這個概念,異常都是在運行的時候捕獲處理。 3)用throw關鍵字,拋出一個異常對象。所有異常都是Throwable的子類型。throw表達式是有類型的,就是Nothing,因爲Nothing是所有類型的子類型,所以throw表達式可以用在需要類型的地方 def test(): Nothing = { throw new Exception("不對") } 4)在Scala裏,借用了模式匹配的思想來做異常的匹配,因此,在catch的代碼裏,是一系列case子句來匹配異常。當匹配上後 => 有多條語句可以換行寫,類似 java 的 switch case x: 代碼塊.. 5)異常捕捉的機制與其他語言中一樣,如果有異常發生,catch子句是按次序捕捉的。因此,在catch子句中,越具體的異常越要靠前,越普遍的異常越靠後,如果把越普遍的異常寫在前,把具體的異常寫在後,在scala中也不會報錯(不報錯,但是不推薦),但這樣是非常不好的編程風格。 6)finally子句用於執行不管是正常處理還是有異常發生時都需要執行的步驟,一般用於對象的清理工作,這點和Java一樣。 7)Scala提供了throws關鍵字來聲明異常。可以使用方法定義聲明異常。它向調用者函數提供了此方法可能引發此異常的信息。 它有助於調用函數處理並將該代碼包含在try-catch塊中,以避免程序異常終止。在scala中,可以使用throws註釋來聲明異常 @throws(classOf[NumberFormatException])//等同於NumberFormatException.class def f11() = { "abc".toInt }