欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)邀請(qǐng)碼778899分享:Scala語(yǔ)言的特性

柚子快報(bào)邀請(qǐng)碼778899分享:Scala語(yǔ)言的特性

http://yzkb.51969.com/

由于Spark是由Scala編寫(xiě)的,為了使用Spark, 需要掌握Scala這門語(yǔ)言。由于Scala與Java有很多相似的地方,所以在Java的基礎(chǔ)上注意其特性就能很快熟悉Scala。

Scala是一門以Java虛擬機(jī)(JVM)為運(yùn)行環(huán)境并將面向?qū)ο蠛秃瘮?shù)式編程的最佳特性結(jié)合在一起的靜態(tài)類型編程語(yǔ)言,它具有以下特點(diǎn):

Scala是一門多范式的編程語(yǔ)言,Scala支持面向?qū)ο蠛秃瘮?shù)式編程。多范式,就是多種編程方法的意思。有面向過(guò)程、面向?qū)ο?、泛型、函?shù)式四種程序設(shè)計(jì)方法。Scala在設(shè)計(jì)時(shí)參考了Java的設(shè)計(jì)思想,將函數(shù)式編程語(yǔ)言的特點(diǎn)融合到JAVA中。Scala源代碼(.scala)會(huì)被編譯成Java字節(jié)碼(.class),然后運(yùn)行于JVM之上,并可以調(diào)用現(xiàn)有的Java類庫(kù),實(shí)現(xiàn)兩種語(yǔ)言的無(wú)縫對(duì)接。Scala單作為一門語(yǔ)言來(lái)看,非常的簡(jiǎn)潔高效。

1 安裝配置

1.1 環(huán)境配置

從Scala官網(wǎng)下載對(duì)應(yīng)版本的壓縮包:https://www.scala-lang.org/download/

解壓到指定目錄后配置環(huán)境變量

之后在命令行輸入scala啟動(dòng)Scala環(huán)境成功

1.2 IDEA創(chuàng)建Scala項(xiàng)目

在IDEA中安裝Scala插件:

點(diǎn)擊 File->Setting->點(diǎn)擊 Plugins->在搜索框輸入 Scala->點(diǎn)擊 Install->點(diǎn)擊 ok->點(diǎn)擊 apply,重啟IDEA后生效

為項(xiàng)目引入Scala框架支持:

在項(xiàng)目文件夾上點(diǎn)擊右鍵-> Add Framework Support… ->選擇 Scala后點(diǎn)擊確定。如果第一次使用需要點(diǎn)擊創(chuàng)建按鈕,引入scala庫(kù)后才會(huì)顯示scala-sdk庫(kù) 3. 創(chuàng)建scala源文件目錄 先創(chuàng)建普通目錄,右鍵點(diǎn)擊 main 目錄->New->點(diǎn)擊 Diretory ->命名為scala 將該目錄標(biāo)記為源文件目錄,右鍵點(diǎn)擊 scala 目錄->Mark Directory as->選擇 Sources root 4. 創(chuàng)建類 右鍵點(diǎn)擊 scala 目錄->New->Scala Class->Kind 項(xiàng)選擇 Object->Name 項(xiàng)輸入類名HelloScala,就生成了一個(gè)scala對(duì)象。輸入以下代碼運(yùn)行控制臺(tái)輸出"hello scala"

object HelloScala {

def main(args: Array[String]): Unit = {

println("hello scala")

}

}

查看HelloScala生成的target文件夾可以看到Object編譯后生成HelloScala$.class和HelloScala.class兩個(gè)文件

HelloScala類中有一個(gè)main()函數(shù),其中調(diào)用HelloScala$的靜態(tài)對(duì)象MODULE$

public final class HelloScala (

public static void main(String[] paramArrayOfString) (

Hello$.MODULE$.main(paramArrayOfString);

}

}

HelloScala$.class文件中通過(guò)靜態(tài)對(duì)象調(diào)用HelloScala$的main()函數(shù),Scala是一個(gè)完全面向?qū)ο蟮恼Z(yǔ)言,所以沒(méi)有靜態(tài)語(yǔ)法,而是通過(guò)伴生對(duì)象單例的方式來(lái)調(diào)用靜態(tài)方法

import scala.Predef.;

public final class HelloScala$ {

public static HelloScala$ MODULE$;

static {

new HelloScala$();

}

public void main(final String[] args) {

.MODULE$.println("hello scala");

}

private HelloScala$() {

MODULE$ = this;

}

}

2 變量

通過(guò)官網(wǎng)可以查看Scala的API:https://www.scala-lang.org/api/2.12.15/scala/index.html

2.1 注釋

Scala 注釋使用和 Java 完全一樣。

//單行注釋

/* 多行注釋 */

/**

* 文檔注釋

*/

2.2 輸入輸出

通過(guò)StdIn讀取鍵盤的標(biāo)準(zhǔn)輸入

// 讀取一行字符串

var name = StdIn.readLine()

// 讀取short

var age = StdIn.readShort()

// 讀取double類型

var sal = StdIn.readDouble()

Scala的輸出除了和Java類似使用println()按行輸出和printf()格式化輸出外,還可以使用三個(gè)雙引號(hào)進(jìn)行多行字符串輸出,其中使用|進(jìn)行拼接

val s =

"""

|select

| name,

| age

|from user

|where name="zhangsan"

""".stripMargin

println(s)

還可以直接在字符串中通過(guò)$引用變量,在${}內(nèi)進(jìn)行變量運(yùn)算,注意要在字符串前面加s

var age=22

println(s"今年我 $age 歲,明年我${age+1}歲")

//輸出:今年我 22 歲,明年我23歲

2.3 變量

Scala用關(guān)鍵字var來(lái)聲明變量,val聲明常量,常量聲明后不可更改,具有以下幾個(gè)特點(diǎn)

類型推導(dǎo):聲明變量時(shí),類型可以省略,編譯器自動(dòng)推導(dǎo)強(qiáng)數(shù)據(jù)類型:類型確定后,就不能修改變量聲明時(shí),必須要有初始值

//var 變量名 [: 變量類型] = 初始值

var i:Int = 10

//val 常量名 [: 常量類型] = 初始值

val j:Int = 20

雖然val對(duì)象本身不變,但是在使用時(shí),其指向的內(nèi)容卻可以改變

class Person{

var name : String = "jinlian"

}

object TestVar {

def main(args: Array[String]): Unit = {

// p1 是 var 修飾的,p1 的屬性可以變,而且 p1 本身也可以變

var p1 = new Person()

p1.name = "dalang"

p1 = null

// p2 是 val 修飾的,那么 p2 本身不可變,它固定地指向一個(gè)內(nèi)存地址

val p2 = new Person()

// p2 = null // 錯(cuò)誤的,因?yàn)?p2 是 val 修飾的

p2.name="jinlian" //但是p2指向的內(nèi)容可以變,內(nèi)存地址中的內(nèi)容可變

}

}

Scala 中的標(biāo)識(shí)符聲明,基本和 Java 一樣以字母或者下劃線開(kāi)頭,后接字母、數(shù)字、下劃線,但是細(xì)節(jié)上會(huì)有所變化。

// 若以操作符開(kāi)頭,則只能包含操作符

var +*-/#! : String = "" // ok

var +*-/#!1 : String = "" // 錯(cuò)誤

//用反引號(hào)`....`包括的任意字符串,即使是關(guān)鍵字

var if : String = "" // error 不能用關(guān)鍵字

var `if` : String = "" // ok 用反引號(hào)包裹

2.4 數(shù)據(jù)類型

Java有基本類型char、int、double等,為了便于使用分別對(duì)其進(jìn)行了包裝產(chǎn)生了包裝類Character、Integer和Double等,所以Java語(yǔ)言并不是真正的面向?qū)ο?。Scala中的一切數(shù)據(jù)都是對(duì)象,基本數(shù)據(jù)類型如下所示:

Scala中一切數(shù)據(jù)都是Any的子類,整體上分為兩大類:數(shù)值類型AnyVal和引用類型AnyRef。其中數(shù)值類型中的Byte、Short、Int、Long、Float、Double低精度的類型可以向高精度類型進(jìn)行自動(dòng)轉(zhuǎn)換。StringOps用于字符串處理,可以看作是Java的String類的增強(qiáng) 整數(shù)類型有Byte、Short、Int、Long,長(zhǎng)度分別為1、2、4、8字節(jié),對(duì)應(yīng)最大可以表示8、16、32、64位有符號(hào)補(bǔ)碼整數(shù)。Scala 的整型,默認(rèn)為 Int 型,聲明 Long 型,須后加l或L。

var n2:Byte = -128

var n3:Byte = 128 // 報(bào)錯(cuò),超過(guò)Byte有符號(hào)補(bǔ)碼所能表示的最大范圍

var n6 = 9223372036854775807L // 聲明Long類型

浮點(diǎn)類型有4字節(jié)32位的單精度浮點(diǎn)類型Float、8字節(jié)64位雙精度浮點(diǎn)數(shù)Double ,均遵循IEEE 754標(biāo)準(zhǔn)。默認(rèn)為 Double 型,聲明 Float 型常量,須后加f或F。

var n7 = 2.2345678912f

var n8 = 2.2345678912

println("n7=" + n7)

println("n8=" + n8)

/*運(yùn)行的結(jié)果

n7=2.2345679

n8=2.2345678912

*/

字符類型Char表示單個(gè)字符,長(zhǎng)度為2字節(jié)。字符常量是用單引號(hào) ’ ’ 括起來(lái)的單個(gè)字符

var c1: Char = 'a'

println("c1=" + c1) // 輸出c1=a

var c2: Char = 'a' + 1

println("c2=" + c2) //輸出c2=b

布爾類型Boolean占 1 個(gè)字節(jié),數(shù)據(jù)只允許取值 true 和 false

數(shù)據(jù)類型Unit表示無(wú)值,只有一個(gè)對(duì)象()。用作方法的返回值,對(duì)應(yīng)于Java中的返回值void,表示方法沒(méi)有返回值。

def main(args: Array[String]): Unit = { // main函數(shù)沒(méi)有返回值

}

Null只有一個(gè)對(duì)象就是null。它是所有引用類型(AnyRef)的子類,因此Null 可以賦值給任意引用類型(AnyRef),但是不能賦值給值類型(AnyVal)

var cat = new Cat();

cat = null // 正確

var n1: Int = null // 錯(cuò)誤

Nothing是所有數(shù)據(jù)類型的子類,主要在函數(shù)沒(méi)有明確返回值時(shí)將結(jié)果返回給任意變量接收,可以作為沒(méi)有正常返回值的方法的返回類型

def test() : Nothing={ // 返回拋出的異常

throw new Exception()

}

自動(dòng)類型轉(zhuǎn)換:當(dāng) Scala 程序在進(jìn)行賦值或者運(yùn)算時(shí),精度小的類型自動(dòng)轉(zhuǎn)換為精度大的數(shù)值類型,按照Byte、Short、Int、Long精度由低到高逐階提升。Byte不會(huì)向Char轉(zhuǎn),但是Char可以在進(jìn)行計(jì)算時(shí)轉(zhuǎn)為Int類型參與計(jì)算。

//多種類型的數(shù)據(jù)混合運(yùn)算時(shí),數(shù)據(jù)轉(zhuǎn)換成高精度類型再進(jìn)行計(jì)算。

var n = 1 + 2.0

println(n) // n為 Double

// Byte和Char轉(zhuǎn)為Int

var b: Byte = 1

var c: Char = 1

var i = b + c

println(i)

強(qiáng)制類型轉(zhuǎn)換可以將數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為目標(biāo)類型,例如可以將數(shù)據(jù)由高精度轉(zhuǎn)換為低精度,使用時(shí)要加上強(qiáng)制轉(zhuǎn)函數(shù),但可能造成精度降低或溢出。強(qiáng)制轉(zhuǎn)換為數(shù)值類型時(shí)的函數(shù)為toInt、toDouble、toByte等類似函數(shù)。如果希望轉(zhuǎn)換為String類型只需要在基本類型值后+“”

// 向低精度轉(zhuǎn)換

var i: Int = 2.5.toInt

println(i) // 輸出2,精度損失

// 字符串轉(zhuǎn)數(shù)值類型

var s1 : String = "12"

var n1 : Byte = s1.toByte

// 轉(zhuǎn)換為字符串

var str1 : String = true + ""

2.5 運(yùn)算符

Scala 運(yùn)算符的使用和 Java 運(yùn)算符的使用基本相同

算術(shù)運(yùn)算符+、-、*、/、%,邏輯運(yùn)算符&&、||、!和Java一樣

關(guān)系運(yùn)算符 >、<、=、!=也相同,Scala中的==會(huì)比較二者的內(nèi)容,類似于Java中的equals

def main(args: Array[String]): Unit = {

val s1 = "abc"

val s2 = new String("abc")

println(s1 == s2) // true 二者中的內(nèi)容相同

println(s1.eq(s2)) // false 但不是同一塊內(nèi)存地址

}

需要注意的是Scala 中沒(méi)有++、–操作符,可以通過(guò)+=、-=來(lái)實(shí)現(xiàn)同樣的效果;

在 Scala 中其實(shí)是沒(méi)有運(yùn)算符的,所有運(yùn)算符都是方法,只不過(guò)在使用時(shí)省略了調(diào)用的.和()

// 標(biāo)準(zhǔn)的加法運(yùn)算

val i:Int = 1.+(1)

// (1)當(dāng)調(diào)用對(duì)象的方法時(shí),.可以省略

val j:Int = 1 + (1)

// (2)如果函數(shù)參數(shù)只有一個(gè),或者沒(méi)有參數(shù),()可以省略

val k:Int = 1 + 1

println(1.toString())

println(1 toString()) //省略.

println(1 toString) //省略()

2.6 流程控制

分支結(jié)構(gòu)

Scala的if分支控制的使用和Java相似

if (age < 18){

println("童年")

}else if(age>=18 && age<30){

println("中年")

}else{

println("老年")

}

Scala的if else表達(dá)式可以用于返回值

val res :String = if (age < 18){

"童年"

}else if(age>=18 && age<30){

"中年"

}else{

"老年"

}

可以用if else實(shí)現(xiàn)三元運(yùn)算符的效果

val res:Any = if (age < 18) "童年" else "成年"

需要注意的是在 Scala 中沒(méi)有 Switch,而是使用模式匹配來(lái)處理。模式匹配采用 match 關(guān)鍵字聲明,每個(gè)分支采用 case 關(guān)鍵字進(jìn)行聲明,匹配時(shí)從第一個(gè) case 分支開(kāi)始,如果匹配成功那么執(zhí)行對(duì)應(yīng)的邏輯代碼;否則繼續(xù)執(zhí)行下一個(gè)分支進(jìn)行判斷。如果所有 case 都不匹配,那么會(huì)執(zhí)行 case _ 分支。

var result = operator match {

case '+' => a + b

case '-' => a - b

case '*' => a * b

case '/' => a / b

case _ => "illegal"

}

模式匹配可以匹配所有的字面量,包括字符串,字符,數(shù)字,布爾值等,還可以對(duì)對(duì)象、集合等復(fù)雜類型進(jìn)行精確的匹配

val result = arr match {

case Array(0) => "0" //匹配 Array(0) 這個(gè)數(shù)組

case Array(x, y) => x + "," + y //匹配有兩個(gè)元素的數(shù)組,然后將將元素值賦給對(duì)應(yīng)的 x,y

case Array(0, _*) => "以 0 開(kāi)頭的數(shù)組" //匹配以 0 開(kāi)頭和數(shù)組

case _ => "something else"

}

循環(huán)結(jié)構(gòu)

Scala中的for循環(huán)有多種推導(dǎo)式

使用關(guān)鍵字to實(shí)現(xiàn)前后閉合的范圍內(nèi)數(shù)據(jù)遍歷

// i 取1、2、3

for(i <- 1 to 3){

print(i + " ")

}

until實(shí)現(xiàn)前閉后開(kāi)的遍歷

// i取1、2

for(i <- 1 until 3) {

print(i + " ")

}

循環(huán)守衛(wèi),即循環(huán)保護(hù)式(也稱條件判斷式,守衛(wèi))。保護(hù)式為 true 則進(jìn)入循環(huán)體內(nèi)部,為 false 則跳過(guò),類似于 continue。

//打印10以內(nèi)的偶數(shù)

for(i <- 1 to 10 if i % 2 == 0) {

print(i + " ")

}

循環(huán)步長(zhǎng)by,擱幾個(gè)數(shù)遍歷

// 擱3個(gè)數(shù)打印一次

for (i <- 1 to 10 by 3) {

println("i=" + i)

}

此外,在for的括號(hào)中可以進(jìn)行嵌套表達(dá)

for(i <- 1 to 3; j <- 1 to 3) {

println(" i =" + i + " j = " + j)

}

// 上面代碼等價(jià)于

for (i <- 1 to 3) {

for (j <- 1 to 3) {

println("i =" + i + " j=" + j)

}

}

還可以在for推導(dǎo)式中引入變量

for(i <- 1 to 3; j = 4 - i) {

println("i=" + i + " j=" + j)

}

使用yield關(guān)鍵字可以將遍歷過(guò)程中處理的結(jié)果返回到一個(gè)新 Vector 集合中。

var res = for(i <-1 to 10) yield {

i * 2

}

println(res) //輸出Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

使用reverse關(guān)鍵字可以從后往前遍歷

// 倒序打印10到1

for(i <- 1 to 10 reverse){

println(i)

}

While 和 do…While 的使用和 Java 語(yǔ)言中用法相同。與 for 語(yǔ)句不同,while 語(yǔ)句沒(méi)有返回值.

Scala 內(nèi)置控制結(jié)構(gòu)特地去掉了 break 和 continue,是為了更好的適應(yīng)函數(shù)式編程,推薦使用函數(shù)式的風(fēng)格解決break和continue的功能,而不是一個(gè)關(guān)鍵字。Scala中使用breakable控制結(jié)構(gòu)來(lái)實(shí)現(xiàn) break 和 continue 功能。

Breaks.breakable(

for (elem <- 1 to 10) {

println(elem)

if (elem == 5) Breaks.break()

}

)

//簡(jiǎn)略寫(xiě)法

breakable {

for (elem <- 1 to 10) {

println(elem)

if (elem == 5) break

}

}

3 函數(shù)式編程

Scala是一個(gè)將面向函數(shù)和面向?qū)ο缶幊掏昝廊诤系恼Z(yǔ)言。函數(shù)式編程是指將問(wèn)題分解成一個(gè)一個(gè)的步驟,將每個(gè)步驟封裝為函數(shù),通過(guò)調(diào)用這些封裝好的步驟解決問(wèn)題。Scala中的萬(wàn)物皆函數(shù),函數(shù)也可以當(dāng)作一個(gè)值進(jìn)行傳遞。

Scala中函數(shù)的定義語(yǔ)法如下

//關(guān)鍵字 函數(shù)名(參數(shù)名:參數(shù)類型):返回值類型

def sum(x: Int, y: Int): Int = {

// 函數(shù)體

x + y

}

3.1 函數(shù)與方法的區(qū)別

函數(shù)是指更為廣泛的未完成某一功能的程序語(yǔ)句的集合。具體地,和Java一樣,將類中的定義的函數(shù)稱之為方法,只能通過(guò)對(duì)象進(jìn)行調(diào)用。而Scala中的函數(shù)可以定義在任何地方,并且可以不借助對(duì)象直接使用。

如下所示,在Person類中首先定義了屬于該類的方法sayHi(),之后在main()方法中又定義了一個(gè)函數(shù)sayHi()。首先通過(guò)直接調(diào)用函數(shù)的方式對(duì)函數(shù)sayHi()進(jìn)行調(diào)用,之后通過(guò)對(duì)象調(diào)用方法sayHi()

object Person {

// 定義對(duì)象的方法

def sayHi(): Unit = {

println("調(diào)用對(duì)象方法sayHi")

}

def main(args: Array[String]): Unit = {

// 定義函數(shù)

def sayHi(): Unit = {

println("調(diào)用函數(shù)sayHi")

}

sayHi() // 輸出:調(diào)用函數(shù)sayHi

Person.sayHi() // 輸出:調(diào)用對(duì)象方法sayHi

}

}

區(qū)分清楚方法和函數(shù)之后需要注意,對(duì)象的方法可以進(jìn)行重載,但是函數(shù)卻沒(méi)有重載和重寫(xiě)的概念

object Person {

def sayHi(): Unit = {

println("調(diào)用對(duì)象方法sayHi")

}

// 方法可以進(jìn)行重載

def sayHi(name: String): Unit = {

println("重載sayHi,我是" + name)

}

def main(args: Array[String]): Unit = {

def sayHi(): Unit = {

println("調(diào)用函數(shù)sayHi")

}

// 函數(shù)無(wú)法重載,報(bào)錯(cuò):此范圍已定義sayHi

def sayHi(name: String): Unit = {

println("重載sayHi,我是" + name)

}

}

}

Scala 語(yǔ)言可以在任何的語(yǔ)法結(jié)構(gòu)中聲明任何的語(yǔ)法,因此可以在隨時(shí)進(jìn)行引入,并且進(jìn)行函數(shù)的嵌套

def main(args: Array[String]): Unit = {

// 隨時(shí)引入

import java.util.Date

new Date()

def test(): Unit ={

def test1(name:String):Unit={

println("函數(shù)可以嵌套定義")

}

}

}

函數(shù)的參數(shù):一般將有默認(rèn)值的參數(shù)放置在參數(shù)列表的后面,

def Person(name: String, sex: String = "男"): Unit = {

}

可變參數(shù)一般放置在最后

def Person(name: String, age: Int*): Unit = {

}

3.2 函數(shù)的省略

為了簡(jiǎn)便,Scala中經(jīng)常遇到函數(shù)省略寫(xiě)法

// 1 return 可以省略,默認(rèn)使用函數(shù)體的最后一行代碼作為返回值

def sum(x: Int, y: Int): Int = {

x + y

}

// 2 如果函數(shù)體只有一行代碼,可以省略花括號(hào)

def sum(x: Int, y: Int): Int = x + y

// 3 返回值類型如果能夠推斷出來(lái),那么可以省略

def sum(x: Int, y: Int) = x + y

// 如果有 return,則不能省略返回值類型

def sum(x: Int, y: Int): Int = {

return x + y

}

// 如果函數(shù)明確聲明 unit,那么 return 關(guān)鍵字不起作用

def fun(): Unit = {

return "return返回"

}

println(fun()) //輸出:()

// 4 如果無(wú)返回值類型,可以省略等號(hào)。無(wú)返回值的函數(shù)稱為過(guò)程

def fun() {

println("無(wú)返回值")

}

// 5 在調(diào)用具有參數(shù)列表的無(wú)參函數(shù)時(shí),括號(hào)可以省略

def fun() = "無(wú)參函數(shù)"

println(fun)

// 沒(méi)有參數(shù)列表的無(wú)參函數(shù),括號(hào)必須省略

def fun = "無(wú)參函數(shù)"

println(fun()) //報(bào)錯(cuò)

println(fun)

3.3 函數(shù)傳遞

函數(shù)不僅可以調(diào)用,還可以作為整體進(jìn)行傳遞。

如下所示定義函數(shù)func,在函數(shù)內(nèi)打印“直接調(diào)用函數(shù)”,并將字符串“函數(shù)返回值”返回。當(dāng)直接用變量res接收時(shí)會(huì)得到func的返回值;而在函數(shù)后面加上_相當(dāng)于把函數(shù)作為一個(gè)整體傳遞給變量f,之后f也可作為函數(shù)執(zhí)行。此外,通過(guò)() => String指定變量f2的類型為:輸入為空、返回值為String類型的函數(shù),那么下劃線也可以省略。

def func(): String = {

println("直接調(diào)用函數(shù)")

return "函數(shù)返回值"

}

val res = func()

println(res) // 輸出“函數(shù)返回值”

val f = func _

f() // 輸出:直接調(diào)用函數(shù)

// 直接傳遞函數(shù)

val f2: () => String = func

f2()

函數(shù)也可以作為參數(shù)值進(jìn)行傳遞。如下所示定義函數(shù)func1,函數(shù)func2接受一個(gè)函數(shù)作為參數(shù),并將其作為函數(shù)在其內(nèi)部調(diào)用。之后調(diào)用func2并將func1作為參數(shù)傳入,執(zhí)行結(jié)果如下。

def func1(): Unit = {

println("調(diào)用func1")

}

def func2(f: () => Unit) = {

print("在func2內(nèi)")

f() // 在函數(shù)內(nèi)部調(diào)用傳入的參數(shù)函數(shù)

}

func2(func1) // 輸出:在func2內(nèi)調(diào)用func1

函數(shù)也能作為返回值返回

def f1() = {

def f2() = {

}

f2 _ // 將函數(shù)作為返回值

}

匿名函數(shù)

就是指沒(méi)有名字的函數(shù),只關(guān)心函數(shù)的實(shí)現(xiàn)而不關(guān)注函數(shù)名。其形式為 (參數(shù)名:參數(shù)類型) => {函數(shù)體}

如下所示首先定義函數(shù)func,以輸入為String輸出為Unit的函數(shù)f作為形參,在其函數(shù)體內(nèi)調(diào)用作為參數(shù)的函數(shù)f。之后在使用func函數(shù)時(shí),將匿名函數(shù)作為參數(shù)傳入,這樣func在接收到參數(shù)后進(jìn)行執(zhí)行,輸出“在func內(nèi)調(diào)用匿名函數(shù)”

def func(f: String => Unit): Unit = {

f("在func內(nèi)調(diào)用")

}

func((s: String) => { println(s + "匿名函數(shù)")}) // 輸出:在func內(nèi)調(diào)用匿名函數(shù)

匿名函數(shù)有如下簡(jiǎn)寫(xiě)的情況

// 1 參數(shù)的類型可以省略,會(huì)根據(jù)形參進(jìn)行自動(dòng)的推導(dǎo)

func((s) => { println(s + "匿名函數(shù)")})

// 2 若只有一個(gè)參數(shù),則圓括號(hào)可以省略

func(s => { println(s + "匿名函數(shù)")})

// 3 函數(shù)如果只有一行,則大括號(hào)也可以省略

func(s => println(s + "匿名函數(shù)"))

// 4 如果參數(shù)只出現(xiàn)一次,則參數(shù)省略用_代替

func(println( _ ))

函數(shù)閉包

將函數(shù)中用到的所有變量和函數(shù)打包在一起保存起來(lái)。這樣在將函數(shù)作為指返回后,即使原來(lái)環(huán)境中的局部變量被釋放掉,函數(shù)仍然可以正常運(yùn)行。

函數(shù)層次化:為了降低函數(shù)的耦合度,將把一個(gè)參數(shù)列表的多個(gè)參數(shù)拆分為多個(gè)參數(shù)列表進(jìn)行傳遞。如下所示,將參數(shù)a、b拆分到了兩個(gè)列表

def f3(a: Int)(b: Int) = {

a + b

}

println(f3(2)(3))

傳名參數(shù)

當(dāng)函數(shù)作為變量進(jìn)行傳遞時(shí),傳遞的不是一個(gè)結(jié)果值,而是一個(gè)代碼塊,每次出現(xiàn)都會(huì)執(zhí)行對(duì)應(yīng)的代碼。在代碼塊作為參數(shù)時(shí)需要根據(jù)返回值指定類型,例如=>Int代表返回值為Int的代碼塊。

def f = () => {

println("f...")

10

}

def foo1(a: Int): Unit = {

println(a)

println(a)

}

foo1(f()) // 傳遞值,f只被調(diào)用一次

/* 輸出

f...

10

10

*/

def foo2(a: => Int): Unit = {

println(a)

println(a)

}

foo2(f()) // 傳遞函數(shù),f被調(diào)用了兩次

/* 輸出

f...

10

f...

10

*/

惰性加載當(dāng)函數(shù)返回值被聲明為 lazy 時(shí),函數(shù)的執(zhí)行將被推遲,直到我們首次對(duì)此取值,該函數(shù)才會(huì)執(zhí)行。這種函數(shù)我們稱之為惰性函數(shù)。

4 面向?qū)ο?/p>

Scala 的面向?qū)ο笏枷牒?Java 的面向?qū)ο笏枷牒透拍钍且恢碌?,并在此基礎(chǔ)上進(jìn)行了補(bǔ)充擴(kuò)展。

4.1 包管理

為了更好地區(qū)分類名,控制訪問(wèn)范圍,Scala也用包Package對(duì)類進(jìn)行管理。不同的是Scala可以在一個(gè)源文件中嵌套聲明多個(gè)package,這樣子包中的類可以直接訪問(wèn)父包中的內(nèi)容

package com{

package tory{

package scala{

}

}

}

關(guān)于包的使用注意以下幾點(diǎn)

在 Scala 中可以為每個(gè)包定義一個(gè)同名的包對(duì)象,其下所有 class 和 object 可以直接訪問(wèn)該包中的成員。和 Java 一樣,可以在頂部使用 import 導(dǎo)入,在這個(gè)文件中的所有類都可以使用。局部導(dǎo)入:什么時(shí)候使用,什么時(shí)候?qū)?。在其作用范圍?nèi)都可以使用通配符導(dǎo)入多個(gè)包:import java.util._給導(dǎo)入的類起名:import java.util.{ArrayList=>AL}屏蔽類:import java.util.{ArrayList =>,}導(dǎo)入一個(gè)包的多個(gè)類:import java.util.{HashSet, ArrayList}導(dǎo)入包的絕對(duì)路徑:new root.java.util.HashMap

4.2 類

一個(gè).scala 文件中可以定義多個(gè)類。Scala 中沒(méi)有 public,默認(rèn)可見(jiàn)性就是公開(kāi)的。但是其底層實(shí)現(xiàn)上是通過(guò)get 方法(obj.field())和 set 方法(obj.field_=(value))來(lái)實(shí)現(xiàn)對(duì)屬性的獲取和賦值的,因此Scala不推薦將屬性設(shè)置為private并通過(guò)getter、setter方法來(lái)操作。但有時(shí)為了和其他Java框架進(jìn)行兼容,也可以通過(guò)@BeanProperty注解為屬性設(shè)置getter和setter方法。

protected 為受保護(hù)權(quán)限,Scala 中受保護(hù)權(quán)限比 Java 中更嚴(yán)格,同類、子類可以訪問(wèn),同包無(wú)法訪問(wèn)。

class Person {

var name: String = "bobo" //定義屬性

var age: Int = _ // _表示給屬性一個(gè)默認(rèn)值,val 修飾的屬性不能賦默認(rèn)值,必須顯示指定

//Bean 屬性(@BeanProperty)

// 通過(guò)注解自動(dòng)生成規(guī)范的 setXxx/getXxx 方法

@BeanProperty

var sex: String = "男"

}

Scala 構(gòu)造對(duì)象也需要調(diào)用構(gòu)造方法,并且可以有任意多個(gè)構(gòu)造方法。Scala 類的構(gòu)造器包括:主構(gòu)造器和輔助構(gòu)造器。

主構(gòu)造器:由于類名和構(gòu)造函數(shù)名是一樣的,那么就可以把類名后面加上形參列表,從而當(dāng)作主構(gòu)造器。構(gòu)造器參數(shù)列表默認(rèn)為局部變量,如果用var修飾就是類成員屬性。如果主構(gòu)造器無(wú)參數(shù),小括號(hào)可省略,構(gòu)建對(duì)象時(shí)調(diào)用的構(gòu)造方法的小括號(hào)也可以省略??梢栽趨?shù)列表()前添加關(guān)鍵字private將主構(gòu)造器變?yōu)樗接?。輔助構(gòu)造器:函數(shù)的名稱 this,可以有多個(gè)進(jìn)行重載。輔助構(gòu)造器無(wú)法直接創(chuàng)建建對(duì)象,必須直接或者間接調(diào)用主構(gòu)造方法。

class Person(var name: String) { // 主構(gòu)造器

var age: Int = _

def this(name: String, age: Int) { // 輔助構(gòu)造器

this(name) // 調(diào)用主構(gòu)造器

this.age = age

}

def sayHi(): Unit = {

println("我叫" + name + ",年齡" + age)

}

}

object Person {

def main(args: Array[String]): Unit = {

val p1 = new Person("小李", 18)

p1.sayHi()

}

}

scala 是單繼承,子類繼承父類的屬性和方法,子類中調(diào)用父類的方法使用 super 關(guān)鍵字。如果重寫(xiě)需要通過(guò)關(guān)鍵字override聲明。

多態(tài)也是通過(guò)動(dòng)態(tài)綁定實(shí)現(xiàn)的。需要注意的是Scala 中屬性和方法都是動(dòng)態(tài)綁定,而 Java 中只有方法為動(dòng)態(tài)綁定。 如下所示,Teacher類為Person類的子類,通過(guò)val teacher1: Person = new Teacher創(chuàng)建一個(gè)Teacher對(duì)象,這里指針p的類型是Person,但是它并沒(méi)有和Person類綁定,而是在運(yùn)行過(guò)程中動(dòng)態(tài)判定其類型,在輸出屬性name和調(diào)用方法hello()時(shí)都輸出了teacher的信息。

class Person {

val name: String = "person"

def hello(): Unit = {

println("hello person")

}

}

class Teacher extends Person {

override val name: String = "teacher" // 重寫(xiě)父類屬性

override def hello(): Unit = { // 重寫(xiě)父類方法

println("hello teacher")

}

}

object Test {

def main(args: Array[String]): Unit = {

val teacher: Teacher = new Teacher()

println(teacher.name)

teacher.hello()

val p: Person = new Teacher

println(p.name) // 輸出teacher

p.hello() // 輸出hello teacher

}

}

如下所示為Java中多態(tài)的實(shí)現(xiàn),同樣定義了Person類的指針p,雖然其方法hello()輸出hello teacher但是其屬性名稱卻是person,可見(jiàn)其方法實(shí)現(xiàn)了動(dòng)態(tài)綁定,而屬性name卻沒(méi)有

public class TestDynamic {

public static void main(String[] args) {

Teacher teacher = new Teacher();

Person p = new Teacher();

System.out.println(teacher.name);

teacher.hello();

System.out.println(p.name); // 輸出person

p.hello(); // 輸出hello teacher

}

}

抽象類:在類屬性定義時(shí),如果一個(gè)屬性沒(méi)有初始化就是抽象屬性,只有在abstract關(guān)鍵字標(biāo)記的抽象類中才能定義抽象屬性和抽象方法,只聲明而沒(méi)有實(shí)現(xiàn)的方法就是抽象方法。如果父類為抽象類,那么子類需要將抽象的屬性和方法實(shí)現(xiàn),否則子類也需聲明為抽象類。

如下所示為三個(gè)類方法

//(1)判斷對(duì)象是否為某個(gè)類型的實(shí)例

val bool: Boolean = person.isInstanceOf[Person]

if ( bool ) {

//(2)將對(duì)象轉(zhuǎn)換為某個(gè)類型的實(shí)例

val p1: Person = person.asInstanceOf[Person]

println(p1)

}

//(3)獲取類的信息

val pClass: Class[Person] = classOf[Person]

枚舉類需要繼承Enumeration,應(yīng)用類需要繼承App

object Color extends Enumeration {

val RED = Value(1, "red")

val YELLOW = Value(2, "yellow")

val BLUE = Value(3, "blue")

}

4.3 單例對(duì)象

Scala語(yǔ)言是完全面向?qū)ο蟮恼Z(yǔ)言,所以并沒(méi)有靜態(tài)的概念。但是為了能夠和Java語(yǔ)言交互,就產(chǎn)生了一種特殊的對(duì)象來(lái)模擬類對(duì)象,該對(duì)象為單例對(duì)象。若單例對(duì)象名與類名一致,則稱該單例對(duì)象這個(gè)類的伴生對(duì)象,這個(gè)類的所有“靜態(tài)”內(nèi)容都可以放置在它的伴生對(duì)象中聲明。

單例對(duì)象采用 object 關(guān)鍵字聲明,單例對(duì)象對(duì)應(yīng)的類稱之為伴生類,伴生對(duì)象的名稱應(yīng)該和伴生類名一致。單例對(duì)象中的屬性和方法都可以通過(guò)伴生對(duì)象名(類名)直接調(diào)用訪問(wèn)。

class Person { // 伴生類

var name: String = "bobo"

}

object Person { // 伴生對(duì)象

var country: String = "China"

}

object Test {

def main(args: Array[String]): Unit = {

// 通過(guò)伴生對(duì)象訪問(wèn)屬性

println(Person.country)

}

}

可以通過(guò)函數(shù)式的風(fēng)格創(chuàng)建對(duì)象,即類名(),其本質(zhì)是在調(diào)用該對(duì)象的 apply() 方法,在apply中調(diào)用構(gòu)造器,進(jìn)而統(tǒng)一面向?qū)ο缶幊毯秃瘮?shù)式編程的風(fēng)格

class Person {

println("調(diào)用主構(gòu)造器")

}

object Person {

def apply(): Person = {

println("調(diào)用apply")

new Person()

}

}

object Test {

def main(args: Array[String]): Unit = {

var p = Person() // 用函數(shù)式的風(fēng)格創(chuàng)建對(duì)象

/* 輸出

調(diào)用apply

調(diào)用主構(gòu)造器

*/

}

}

4.4 Trait

Scala 語(yǔ)言中采用特質(zhì) trait(特征)來(lái)代替接口的概念,即將具有相同特征的多個(gè)類抽象出來(lái),聲明為trait

trait 中即可以有抽象屬性和方法,也可以有具體的屬性和方法。

trait PersonTrait {

// 聲明屬性

var name:String = _

// 聲明方法

def eat():Unit={

}

// 抽象屬性

var age:Int

// 抽象方法

def say():Unit

}

與Java只能實(shí)現(xiàn)一個(gè)接口不同,一個(gè)類可以混入(mixin)多個(gè)特質(zhì),這也是對(duì)Scala單繼承機(jī)制的一種補(bǔ)充。如果有多個(gè)特質(zhì)或存在父類,那么需要采用 with關(guān)鍵字連接。所有的 Java 接口都可以當(dāng)做 Scala 特質(zhì)使用。還可以在創(chuàng)建對(duì)象時(shí)動(dòng)態(tài)混入trait。

// 繼承多個(gè)trait

class Teacher extends PersonTrait with java.io.Serializable {

override def say(): Unit = {

println("say")

}

override var age: Int = _

}

object TestTrait {

def main(args: Array[String]): Unit = {

// 動(dòng)態(tài)混入:靈活擴(kuò)展對(duì)象

val t2 = new Teacher with SexTrait {

override var sex: String = "男"

}

//調(diào)用混入 trait 的屬性

println(t2.sex)

}

}

當(dāng)混入的特質(zhì)中具有相同的方法造成沖突時(shí):

如果兩個(gè) trait 之間沒(méi)有任何關(guān)系,則直接在中重寫(xiě)沖突方法兩個(gè) trait A、B繼承自相同的 trait C,采用特質(zhì)疊加:將混入的多個(gè) trait 中的沖突方法疊加起來(lái),依次執(zhí)行A、B、C的部分

4.5 泛型

Scala在傳統(tǒng)泛型的基礎(chǔ)上還針對(duì)集合增加了協(xié)變和逆變

協(xié)變:Son 是 Father 的子類,則 MyList[Son] 也作為 MyList[Father]的“子類”。逆變:Son 是 Father 的子類,則 MyList[Son]作為 MyList[Father]的“父類”。

class MyList[+T]{ //協(xié)變

}

class MyList[-T]{ //逆變

}

class MyList[T] //不變

泛型還可以通過(guò)上下限對(duì)傳入的類型進(jìn)行限定,上限就是指?jìng)魅氲膮?shù)

Class PersonList[T <: Person]{ //泛型上限,傳入的類型T為Person的子類或自身

}

Class PersonList[T >: Person]{ //泛型下限,傳入Person或其父類

}

5 集合

Scala 的集合有三大類:序列 Seq、集 Set、映射 Map,所有的集合都擴(kuò)展自 Iterable。對(duì)于幾乎所有的集合類,Scala 都同時(shí)提供了可變和不可變的版本

不可變集合:scala.collection.immutable。集合對(duì)象不可修改,每次修改就會(huì)返回一個(gè)新對(duì)象,類似于 java 中的 String 對(duì)象可變集合: scala.collection.mutable??梢灾苯訉?duì)原對(duì)象進(jìn)行修改,而不會(huì)返回新的對(duì)象。類似于 java 中 StringBuilder 對(duì)象

如下所示為不可變集合繼承圖 下圖為可變集合

集合常見(jiàn)的共有函數(shù)如下所示

//(1)獲取集合長(zhǎng)度

println(list.length)

//(2)獲取集合大小,等同于 length

println(list.size)

//(3)循環(huán)遍歷

list.foreach(println)

//(4)迭代器

for (elem <- list.itera tor) {

println(elem)

}

//(5)生成字符串

println(list.mkString(","))

//(6)是否包含

println(list.contains(3))

5.1 數(shù)組

如下所示為對(duì)不可變數(shù)組Array進(jìn)行定義和訪問(wèn)的常見(jiàn)方法

// 1 數(shù)組定義,長(zhǎng)度為4的Int型數(shù)組

val arr01 = new Array[Int](4)

println(arr01.length) // 4

// 1.2 使用函數(shù)式的apply方法創(chuàng)建數(shù)組并直接賦初值

val arr1 = Array(1, 2)

//(2)數(shù)組賦值

//(2.1)修改某個(gè)元素的值

arr01(3) = 10

//(2.2)采用方法的形式給數(shù)組賦值

arr01.update(0,1)

//(3)遍歷數(shù)組

//(3.1)打印數(shù)組

println(arr01.mkString(","))

//(3.2)普通遍歷

for (i <- arr01) {

println(i)

}

//(3.3)對(duì)每個(gè)元素使用函數(shù)

def printx(elem:Int): Unit = {

println(elem)

}

arr01.foreach(printx)

arr01.foreach(println)

//(4)增加元素(由于創(chuàng)建的是不可變數(shù)組,增加元素其實(shí)是產(chǎn)生新的數(shù)組)

val ints: Array[Int] = arr01 :+ 5

println(ints)

如下所示為可變數(shù)組ArrayBuffer的使用

//(1)創(chuàng)建并初始賦值可變數(shù)組

val arr01 = ArrayBuffer[Any](1, 2, 3)

println(arr01.length) // 3

println("arr01.hash=" + arr01.hashCode())

//(2)遍歷數(shù)組

for (i <- arr01) {

println(i)

}

//(3)增加元素

//(3.1)追加數(shù)據(jù)

arr01.+=(4)

//(3.2)向數(shù)組最后追加數(shù)據(jù)

arr01.append(5,6)

//(3.3)向指定的位置插入數(shù)據(jù)

arr01.insert(0,7,8)

println("arr01.hash=" + arr01.hashCode()) // 數(shù)組的哈希值不變

//(4)修改元素

arr01(1) = 9 //修改第 2 個(gè)元素的值

通過(guò)arr1.toBuffer 可以將不可變數(shù)組轉(zhuǎn)可變數(shù)組,arr2.toArray 將可變數(shù)組轉(zhuǎn)不可變數(shù)組

如下所示為多維數(shù)組的創(chuàng)建和使用

// 創(chuàng)建一個(gè)3×4的二維數(shù)組

val arr = Array.ofDim[Int](3, 4)

arr(1)(2) = 88

//(2)遍歷二維數(shù)組

for (a <- arr) { //a 就是一維數(shù)組

for (i <- a) {

print(i + " ")

}

println()

}

5.2 List

如下所示為不可變List的創(chuàng)建和使用

//創(chuàng)建一個(gè) List(數(shù)據(jù)有順序,可重復(fù))

val list: List[Int] = List(1,2,3,4,3)

// 訪問(wèn)元素

println(list(0))

// 遍歷

list.foreach(println)

// 增加數(shù)據(jù)

val list2 = list.+:(5)

// 將元素5添加到集合,運(yùn)算規(guī)則從右向左

val list1 = 5::list

// 將集合list拆分成單個(gè)元素后逐個(gè)添加到list1

val list2 = list ::: list1

如下所示為可變 ListBuffer的創(chuàng)建和使用

//(1)創(chuàng)建一個(gè)可變集合

val buffer = ListBuffer(1,2,3,4)

//(2)向集合中添加數(shù)據(jù)

buffer.+=(5)

buffer.append(6)

buffer.insert(1,2)

//(3)打印集合數(shù)據(jù)

buffer.foreach(println)

//(4)修改數(shù)據(jù)

buffer(1) = 6

buffer.update(1,7)

//(5)刪除數(shù)據(jù)

buffer.-(5)

5.3 Set集合

如下所示為不可變集合Set的使用

//(1)Set 默認(rèn)是不可變集合,數(shù)據(jù)無(wú)序

val set = Set(1,2,3,4,5,6)

//(2)數(shù)據(jù)不可重復(fù)

val set1 = Set(1,2,3,4,5,6,3)

//(3)遍歷集合

for(x<-set1){

println(x)

}

默認(rèn)情況下Scala 使用的是不可變集合,如果想使用可變集合需要引用scala.collection.mutable.Set

//(1)創(chuàng)建可變集合

val set = mutable.Set(1,2,3,4,5,6)

//(3)集合添加元素

set += 8

//(4)向集合中添加元素,返回一個(gè)新的 Set

val ints = set.+(9)

//(5)刪除數(shù)據(jù)

set-=(5)

5.4 Map集合

如下所示為不可變集合Map

//(1)創(chuàng)建不可變集合 Map

val map = Map( "a"->1, "b"->2, "c"->3 )

//(2)循環(huán)打印

map.foreach((kv)=>{println(kv)})

//(3)訪問(wèn)數(shù)據(jù)

for (elem <- map.keys) {

// 使用 get 訪問(wèn) map 集合的數(shù)據(jù)

println(elem + "=" + map.get(elem).get)

}

//(4)如果 key 不存在,返回 0

println(map.get("d").getOrElse(0))

println(map.getOrElse("d", 0))

使用可變集合需要引入mutable.Map

//(1)創(chuàng)建可變集合

val map = mutable.Map( "a"->1, "b"->2, "c"->3 )

//(3)向集合增加數(shù)據(jù)

map.+=("d"->4)

// 將數(shù)值 4 添加到集合,并把集合中原值 1 返回

val maybeInt: Option[Int] = map.put("a", 4)

println(maybeInt.getOrElse(0))

//(4)刪除數(shù)據(jù)

map.-=("b", "c")

//(5)修改數(shù)據(jù)

map.update("d",5)

map("d") = 5

5.5 集合函數(shù)

集合集成了許多常用的操作函數(shù)

//(1)獲取集合的頭

println(list1.head)

//(2)獲取集合的尾(不是頭的就是尾)

println(list1.tail)

//(3)集合最后一個(gè)數(shù)據(jù)

println(list1.last)

//(4)集合初始數(shù)據(jù)(不包含最后一個(gè))

println(list1.init)

//(5)反轉(zhuǎn)

println(list1.reverse)

//(6)取前(后)n 個(gè)元素

println(list1.take(3))

println(list1.takeRight(3))

//(7)去掉前(后)n 個(gè)元素

println(list1.drop(3))

println(list1.dropRight(3))

//(8)并集

println(list1.union(list2))

//(9)交集

println(list1.intersect(list2))

//(10)差集

println(list1.diff(list2))

//(11)拉鏈 注:如果兩個(gè)集合的元素個(gè)數(shù)不相等,那么會(huì)將同等數(shù)量的數(shù)據(jù)進(jìn)行拉鏈,多余的數(shù)據(jù)省略不用

println(list1.zip(list2))

//(12)滑窗

list1.sliding(2, 5).foreach(println)

還有一些計(jì)算有關(guān)的函數(shù)

//(1)求和

println(list.sum)

//(2)求乘積

println(list.product)

//(3)最大值

println(list.max)

//(4)最小值

println(list.min)

//(5)排序

// (5.1)按照元素大小排序

println(list.sortBy(x => x))

// (5.2)按照元素的絕對(duì)值大小排序

println(list.sortBy(x => x.abs))

// (5.3)按元素大小升序排序

println(list.sortWith((x, y) => x < y))

// (5.4)按元素大小降序排序

println(list.sortWith((x, y) => x > y))

如下所示為對(duì)集合元素進(jìn)行操作的函數(shù)

//(1)過(guò)濾

println(list.filter(x => x % 2 == 0))

//(2)轉(zhuǎn)化/映射

println(list.map(x => x + 1))

//(3)扁平化

println(nestedList.flatten)

//(4)扁平化+映射 注:flatMap 相當(dāng)于先進(jìn)行 map 操作,在進(jìn)行 flatten操作

println(wordList.flatMap(x => x.split(" ")))

//(5)分組

println(list.groupBy(x => x % 2))

// 6 聚合

val list = List(1,2,3,4)

val i1 = list.reduceLeft((x,y) => x-y)

val i2 = list.reduceRight((x,y) => x-y) // 4-3-2-1=-2

6 異常

Scala的異常處理和Java類似,將可疑代碼封裝在 try 塊中,之后使用了一個(gè) catch 處理程序來(lái)捕獲異常。如果發(fā)生任何異常,catch 處理程序?qū)⑻幚硭绦驅(qū)⒉粫?huì)異常終止。最后無(wú)論是否異常都執(zhí)行finally子句。

try {

var n= 10 / 0

}catch {

case ex: ArithmeticException=>{

// 發(fā)生算術(shù)異常

println("發(fā)生算術(shù)異常")

}

case ex: Exception=>{

// 對(duì)異常處理

println("發(fā)生了異常 1")

println("發(fā)生了異常 2")

}

}finally {

println("finally")

}

但是 Scala 沒(méi)有“checked(編譯期)”異常, 即 Scala 沒(méi)有編譯異常這個(gè)概念,異常都是在運(yùn)行的時(shí)候捕獲處理。

用 throw 關(guān)鍵字,拋出一個(gè)異常對(duì)象。所有異常都是 Throwable 的子類型。throw 表達(dá)式是有類型的,就是 Nothing,因?yàn)?Nothing 是所有類型的子類型,所以 throw 表達(dá)式可以用在需要類型的地方

def test():Nothing = {

throw new Exception("異常")

}

柚子快報(bào)邀請(qǐng)碼778899分享:Scala語(yǔ)言的特性

http://yzkb.51969.com/

精彩鏈接

評(píng)論可見(jiàn),查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/18874668.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄