Scala教程
SCALA
第一章 Scala入門
1.1 概述
1.1.1 Scala簡介
Scala的全稱為Scalable Language,即“可伸縮的語言”, 其設(shè)計(jì)目標(biāo)是希望伴隨著用戶的需求一起成長。 Scala是一門綜合了面向?qū)ο蠛秃瘮?shù)式編程概念的靜態(tài)類型的編程語言, 它運(yùn)行在標(biāo)準(zhǔn)的java平臺(tái)上,可以與所有的Java類庫無縫操作 Spark,Kafka等底層都是Scala編寫的1.1.2 Scala的發(fā)展
馬丁·奧德斯基 追求簡潔高效 決定將函數(shù)式編程語言的特點(diǎn)融合到JAVA中,由此發(fā)明了兩種語言pizza和scala JDK5.0泛型、增強(qiáng)for循環(huán)、自動(dòng)類型轉(zhuǎn)換等都是從Pizza引入的新特性 JDK8.0的類型推斷、lambda表達(dá)式就是從Scala中引入的特性1.1.3 Scala和Java的關(guān)系
Scala基于JVM 參考了Java的思想,可以說是源于Java,Java的進(jìn)階版1.1.4 Scala語言特點(diǎn)
Scala是面向?qū)ο蟮? 每個(gè)值都是對(duì)象,每個(gè)方法都是調(diào)用。 Scala是函數(shù)式的 Scala是功能完整的函數(shù)式編程語言,函數(shù)式編程以兩大理念為指導(dǎo):函數(shù)是一等公民程序中的操作應(yīng)該將輸入值映射成輸出值,而不是當(dāng)場修改數(shù)據(jù)。即方法不應(yīng)該有副作用 以JVM為運(yùn)行環(huán)境的融合語言 面向?qū)ο蠛秃瘮?shù)式編程1.1.5 Scala的優(yōu)點(diǎn)
與Java兼容 精簡的語法 高級(jí)語言特性 靜態(tài)類型1.2 Scala環(huán)境搭建
1.2.1 安裝jdk1.8
Spark3.0基于Scala2.121.2.2 安裝Scala插件
打開IDEA,依次點(diǎn)擊Files=>settings=>plungins選項(xiàng)卡,搜索Scala,安裝重啟即可1.2.3 創(chuàng)建Scala項(xiàng)目
在IDEA中依次點(diǎn)擊File=>New=>Project,然后選擇創(chuàng)建Scala-IDEA工程1.2.4 下載Scala SDK
在上一步中,此時(shí)看到Scala為空,依次點(diǎn)擊Create=>Download,選擇所需版本后, 點(diǎn)擊ok進(jìn)行下載,下載完成點(diǎn)擊finish進(jìn)入工程1.2.5 創(chuàng)建HelloWorld
在工程src目錄上右點(diǎn)擊New=>Scala Class創(chuàng)建 選擇Scala Object,輸入名稱完成創(chuàng)建1.2.6 切換Scala版本
在日常的開發(fā)中,由于對(duì)應(yīng)軟件,如Spark版本的切換,可能導(dǎo)致需要切換Scala的版本,則 可以在Project Structures中的Global Libraries選項(xiàng)卡中進(jìn)行切換1.3 Scala伴生對(duì)象
Scala編譯后生成兩個(gè)文件 一個(gè).class文件,一個(gè)$.class文件 類叫做伴生對(duì)象的聲明類 對(duì)象叫做類的伴生對(duì)象 Hello.class 程序執(zhí)行的入口類或者當(dāng)前對(duì)象的伴生類 Hello$.class 當(dāng)前伴生對(duì)象的所屬類 object 單例對(duì)象和伴生對(duì)象是為了解決刪除靜態(tài)static關(guān)鍵字之后,而且要實(shí)現(xiàn)靜態(tài)功能而設(shè)計(jì)的 基于對(duì)象來調(diào)用,實(shí)現(xiàn)完全面向?qū)ο?1.4 關(guān)聯(lián)Scala源碼
按住CTRL鍵,~~,將Scala源碼下載下來1.5 官方編程指南
1.在線查看 2.下載解壓scala-docs-2.11.8.zip第二章 變量和數(shù)據(jù)類型
2.1 注釋
和Java一樣 單行注釋// 多行注釋/* */ 文檔注釋/****/ 代碼規(guī)范:使用Tab鍵Shift+tab縮進(jìn)格式化:CTRL+alt+L運(yùn)算符兩邊各加一個(gè)空格一行不超過80個(gè)字符 實(shí)例:/chapter2/Test01.scala2.2 變量和常量
Scala的變量分為兩種 var 可以被重新賦值 val 不可以修改 var i:Int=10 scala將類型放在后面,表示它的類型并不重要 程序員要關(guān)注的東西是變量的名稱,業(yè)務(wù)處理的邏輯 類型是計(jì)算機(jī)底層需要考慮的問題,跟代碼邏輯沒什么關(guān)系 Scala的編譯器是可以對(duì)類型自動(dòng)推斷的 能使用常量的地方盡量不使用變量* 聲明變量時(shí),類型可以省略,編譯器可以總動(dòng)推導(dǎo)* 類型確定后,就不能修改,說明Scala是強(qiáng)數(shù)據(jù)類型語言* 變量聲明時(shí),必須要有初始值* var修飾的可修改,val修飾的不可修改 實(shí)例:/chapter2/Test02.scala2.3 標(biāo)識(shí)符和命名規(guī)范
2.4 字符串輸出
2.5 鍵盤輸入
2.6 數(shù)據(jù)類型
Scala中一切數(shù)據(jù)都是對(duì)象,都是Array子類2.6.1 整數(shù)類型
整型分類:
byte,short,int,long 分別是8位,16位,32位,64位2.6.2 浮點(diǎn)類型
2.6.3 字符類型
2.6.4 布爾類型
2.6.5 Unit類型
Unit表示空值,null類型只有一個(gè)實(shí)例值null nothing類型啥也沒有:有可能拋出異常,返回值就可以指定為nothing2.7 類型轉(zhuǎn)換
2.7.1 自動(dòng)類型轉(zhuǎn)換
自動(dòng)提升原則:當(dāng)有多種類型的數(shù)值混合運(yùn)算時(shí),系統(tǒng)首先自動(dòng)將所有的數(shù)據(jù)轉(zhuǎn)換成精度大的那種數(shù)據(jù)類型 低精度可以賦值給高精度,但反過來不行 (byte,short)和char之間不會(huì)自動(dòng)相互轉(zhuǎn)換,若要轉(zhuǎn)換,則先轉(zhuǎn)換為int類型2.7.2 強(qiáng)制類型轉(zhuǎn)換
將數(shù)據(jù)由高精度轉(zhuǎn)換為低精度,就需要使用到強(qiáng)制類型轉(zhuǎn)換 強(qiáng)轉(zhuǎn)換顧好只針對(duì)最近的操作數(shù)有效,往往會(huì)使用小括號(hào)提高優(yōu)先級(jí)2.7.3 數(shù)值類型和String類型
1.數(shù)值類型轉(zhuǎn)String val a:Int=12 val s:String=a+“” 2.String類型轉(zhuǎn)數(shù)值第三章 運(yùn)算符
3.1 算術(shù)運(yùn)算符
+字符串相加
val re1=10/3 println(re1) val re2:Double=10/3 println(re2) val re3:Double=10.0/33.2 關(guān)系運(yùn)算符
==3.3 邏輯運(yùn)算符
&& || ! 連接多個(gè)條件3.4 賦值運(yùn)算符
Scala里面沒有++,--等 可以通過+=,-=等來實(shí)現(xiàn)3.5 位運(yùn)算符
& | ^ ~ < < >> >>>3.6 Scala運(yùn)算符本質(zhì)
運(yùn)算符的本質(zhì)是一個(gè)對(duì)象的方法調(diào)用
val n1:Int=12 val n2:Int=13 println(n1.+(n2))第四章 流程控制
4.1 分支控制
if else 特別的地方: 有返回值,定義為當(dāng)前分支最后一個(gè)語句的值。 val res=if(age>=18) "成年" else "未成年"4.2 嵌套分支
年齡18,12,6,35,604.3 Switch分支結(jié)構(gòu)
4.4 for循環(huán)控制
####4.4.1范圍數(shù)據(jù)循環(huán)to
for循環(huán)的特性被稱為for推導(dǎo)式
4.4.2 范圍數(shù)據(jù)循環(huán)until
for(i <- 1 until 10)println(i) for(i<-Array(10,20,30))println(i)4.4.3 循環(huán)守衛(wèi)
for(i<- -1 to 3 if i!=2)println(i)4.4.5 循環(huán)步長
//循環(huán)步長,by是一個(gè)方法,是Range中的一個(gè)方法,(1 to 10).by()for(i<-1 to 10 by 2)println(i)for(i<-13 to 30 by 3)println(i)for(i<-13 to 0 by -2)println(i)for(i<-1 to 10 reverse)println(i)//步長不能為0//含笑半步顛for(i<-1.0 to 10.0 by 0.5)println(i)4.4.6 嵌套循環(huán)
//循環(huán)嵌套for(i<-1 to 10;j<-1 to 3)println(i*j)4.4.7 循環(huán)引入變量
//循環(huán)引入變量for(i<- 1 to 10){val j=10-iprintln(i,j)}for(i<-1 to 10;j=10-i)println(i,j)//打印輸出九層妖塔for(i<-1 to 9;j=9-i){println(" "* j + "*"*(2*i-1))}4.4.8 循環(huán)返回值
val res=for(i<-1 to 10)yield i4.5 While 和 do…while循環(huán)控制
1,在Scala中不推薦使用while循環(huán),while必須在外部定義變量,while沒有for循環(huán)的得到返回值用法 2.真正的函數(shù)式語言沒有循環(huán)的,4.6 循環(huán)中斷
Scala內(nèi)部控制結(jié)構(gòu)去掉了break和continue
// 1. 采用拋出異常的方式退出循環(huán) try{for(i<-0 until 4){if(i==3){throw new RuntimeException}println(i)}}catch {case e:Exception=> //什么都不做}// 2. 為了簡化,使用Scala中的Breaks類的break方法,實(shí)現(xiàn)異常的拋出和捕捉Breaks.breakable(for(i<-1 to 4){if(i==3){Breaks.break();}println(i)})println("=============")import scala.util.control.Breaks._breakable(for(i<-1 to 4){if(i==3){break();}println(i)})第五章 函數(shù)式編程
1.面向?qū)ο缶幊?/strong>
Scala語言是一個(gè)完全面向?qū)ο缶幊陶Z言。萬物皆對(duì)象 對(duì)象的本質(zhì):對(duì)數(shù)據(jù)和行為的一個(gè)封裝2.函數(shù)式編程
函數(shù)式編程,解決問題時(shí),將問題分解成一個(gè)一個(gè)的步驟,將每個(gè)步驟進(jìn)行封裝(函數(shù)),通過調(diào)用 當(dāng)成一個(gè)數(shù)學(xué)題的求解,所有的都是一個(gè)表達(dá)式求值的過程 真正的函數(shù)式編程語言里沒有變量,所有的值來了之后都是常量,所以在scala中能用val的地方就用val 解決問題的過程就是不停的求表達(dá)式的值的過程 真正的函數(shù)式編程的本質(zhì)是映射表達(dá)式求值。 函數(shù)式編程,有一個(gè)非常好的特性,對(duì)于函數(shù)而言是不可變的,這就可以做一個(gè)分布式的處理 彼此之間沒有額外的影響5.1 函數(shù)基礎(chǔ)
5.1.1 函數(shù)的基本語法
def funcname(x:Int,y:Int):Unit={println(x+y)} 關(guān)鍵字 函數(shù)名稱 參數(shù) 返回類型 函數(shù)體5.1.2 函數(shù)的和方法的區(qū)別
函數(shù):為完成某一功能的程序語句的集合,稱為函數(shù) 方法:類中的函數(shù)稱之為方法 object Test01 {def main(args: Array[String]): Unit = {//定義函數(shù)def sayHi(name:String):Unit={println("hi "+name)}//調(diào)用函數(shù)sayHi("gaio")//調(diào)用對(duì)象方法Test01.sayHi("gao")}//定義對(duì)象的方法def sayHi(name:String):Unit={println("hi hi "+name)}}5.1.3 函數(shù)定義
參數(shù) 返回值5.1.4 函數(shù)參數(shù)
1.可變參數(shù) 2.如果參數(shù)列表中存在多個(gè)參數(shù),那么可變參數(shù)一般放置在最后 3.參數(shù)默認(rèn)值,一般將有參數(shù)的默認(rèn)值 //1.可變參數(shù)def f1(str:String*):Unit={println(str)}f1("alice")f1("alice","bob")//2.如果參數(shù)列表中存在多個(gè)參數(shù),那么可變參數(shù)一般放置在最后def f2(str1:String,str2:String*):Unit={println(str1,str2)}f2("alice")f2("alice","bob")//3.參數(shù)默認(rèn)值def f3(str:String="hi"):Unit={println(str)}f3()f3("hihihi")//4.帶名參數(shù)def f4(name:String="hi",age:Int):Unit={println(s"$age $name")}f4("bob",23)f4(age=24,name="hihanpi")f4(age=23)5.1.5 函數(shù)至簡原則
能省則省 至簡原則細(xì)節(jié):
//函數(shù)至簡原則def f0(name:String):String={return name}println(f0("hi"))//1.return 可以省略,Scala會(huì)使用函數(shù)體的最后一行代碼作為返回值def f1(name:String):String={name}println(f1("hi1"))//2.如果函數(shù)體里面只有一行代碼,則可以省略花括號(hào)def f2(name:String):String=nameprintln(f2("hi2"))//3.返回值的類型如果能夠推斷出來,則可以省略(:和返回值類型一起省略)def f3(name:String)=name//4.如果函數(shù)體里有return,則返回類型不能省略def f4()={}//5.如果函數(shù)明確聲明Unit,則即使函數(shù)體中使用return關(guān)鍵字也不起作用def f5():Unit={return 1}println(f5())//6.Scala如果期望是無返回值類型,可以省略等號(hào)def f6(){//有時(shí)候被稱為過程println("hi")}//7.如果函數(shù)無參數(shù),那么小括號(hào)可以省略,調(diào)用時(shí)小括號(hào)可以省略def f7(): Unit ={println("hi")}f7()f7//8.如果沒有參數(shù)列表,那么小括號(hào)可以省略,調(diào)用時(shí)小括號(hào)必須省略def f8:Unit={println("hi")}f8//9.如果我們不關(guān)心名稱,只關(guān)心處理邏輯,那么函數(shù)名def可以省略(name:String)=>{println("hi")} //匿名函數(shù),lambda5.2 函數(shù)高級(jí)
5.2.1 高階函數(shù)
在Scala中,函數(shù)地位很高,一方面,我們在代碼的任何地方,可以聲明定義一個(gè)函數(shù),非常靈活 函數(shù)作為一個(gè)表達(dá)式的值,可以有更加高階的用法:函數(shù)可以作為值傳遞函數(shù)可以作為參數(shù)傳遞函數(shù)可以作為函數(shù)返回值返回 val fun=(name:String)=>{println(name)} //匿名函數(shù),lambdafun("hi")//定義一個(gè)函數(shù),以函數(shù)作為參數(shù)輸入def f(func:String=>Unit)={func("hi")}f(fun)f((name:String)=>{println(name)})//匿名函數(shù)的簡化原則f((name:String)=>{println(name)})//1.參數(shù)的類型可以省略,會(huì)根據(jù)形參進(jìn)行自動(dòng)的推導(dǎo)f((name)=>{println(name)})//2.類型省略之后,發(fā)現(xiàn)只有一個(gè)參數(shù),則圓括號(hào)可以省略;其它情況:沒有參數(shù)和參數(shù)超過1的永遠(yuǎn)不能省略圓括號(hào)f(name=>{println(name)})//3.匿名函數(shù)如果只有一行,則大括號(hào)也可以省略f(name=>println(name))//4.如果參數(shù)只出現(xiàn)一次,則參數(shù)省略且后面參數(shù)可用_代替f(println(_))//5.如果可以推斷出,當(dāng)前傳入的println是一個(gè)函數(shù)體,而不是調(diào)用語句,可以直接省略下劃線f(println)5.2.2 匿名函數(shù)
匿名函數(shù)沒有名字(x:Int)=>{函數(shù)體}
//實(shí)例操作,定義一個(gè)“二元運(yùn)算”函數(shù),只操作1和2兩個(gè)數(shù),但是具體運(yùn)算通過參數(shù)傳入def dualFunctionOneAndTwo(fun:(Int,Int)=>Int):Int={fun(1,2)}val add=(a:Int,b:Int)=>a+bval minus=(a:Int,b:Int)=>a-bprintln(dualFunctionOneAndTwo(add))println(dualFunctionOneAndTwo(minus))//匿名函數(shù)簡化println(dualFunctionOneAndTwo((a:Int,b:Int)=>a+b))println(dualFunctionOneAndTwo((a,b)=>a+b))println(dualFunctionOneAndTwo(_+_))println(dualFunctionOneAndTwo(_-_))println(dualFunctionOneAndTwo(-_+_)) //b-a5.2.3 高階函數(shù)案例
5.2.4 函數(shù)柯里化&閉包
5.2.5 遞歸
5.2.6 控制抽象
5.2.7 惰性函數(shù)
第六章 面向?qū)ο?/h2>
Scala的面向?qū)ο蠛蚃ava的面向?qū)ο笏枷牒透拍钍且恢钡?#xff0c;類的概念,對(duì)象的概念
Scala又補(bǔ)充了很多的功能
6.1 Scala包
package 包名
Scala包的作用-和Java一樣區(qū)分相同名字的類當(dāng)類很多時(shí),可以很好的管理控制訪問范圍
6.1.1 包的命名
命名規(guī)則:只能包含數(shù)字,字母,小花仙,小圓點(diǎn)(分隔符),不能使用關(guān)鍵字,不能數(shù)字開頭
命名規(guī)范: com.公司名.項(xiàng)目名.業(yè)務(wù)模塊名.xxx
6.1.2 包說明(包語句)
1.包名和源文件所在路徑不要求必須一致
2.花括號(hào)嵌套
6.1.3 包對(duì)象
在Scala中可以為每個(gè)包定義一個(gè)同名的包對(duì)象,
定義在包對(duì)象中的成員,作為其對(duì)應(yīng)包下所有class和object的共享變量,可以被直接訪問
package object name{}
6.1.4 導(dǎo)包說明
和Java一樣,頂部導(dǎo)入
局部導(dǎo)入,什么時(shí)候用,什么時(shí)候import
通配符導(dǎo)入_
給包中的類重新起名import java.util.{ArrayList=>JL}
導(dǎo)入相同包的多個(gè)函數(shù)import java.util.{HashSet,ArrayList}
屏蔽類import.java.util.{ArrayList=>_,_}
注意:Scala中三個(gè)默認(rèn)導(dǎo)入:
6.2 類和對(duì)象
類:可以堪稱一個(gè)模板
對(duì)象:表示具體的事物
6.2.1 定義類
1.基本語法
[修飾符]類名
6.2.2 屬性
6.3 封裝
6.1.5 訪問權(quán)限
Scala中默認(rèn)訪問權(quán)限為public,但是Scala中沒有public關(guān)鍵字
private為私有權(quán)限,只在類的內(nèi)部和伴生對(duì)象中可用
protected為受保護(hù)權(quán)限,Scala中受保護(hù)權(quán)限比Java中更嚴(yán)格,同類、子類可以訪問,同包無法訪問
private[包名]增加包訪問權(quán)限,包名下其它類也可以使用
6.2.3 方法
6.2.4 創(chuàng)建對(duì)象
6.2.5 構(gòu)造器
和Java一樣,Scala構(gòu)造對(duì)象也需要調(diào)用構(gòu)造方法,并且可以有任意多個(gè)構(gòu)造方法
Scala類的構(gòu)造器包括:主構(gòu)造器和輔助構(gòu)造器基本語法class 類名(形參列表){ //主構(gòu)造器//類體def this(形參列表){//輔助構(gòu)造器}def this(形參列表){//輔助構(gòu)造器可以有多個(gè)}}說明:1.輔助構(gòu)造器,函數(shù)的名稱this,可以有多個(gè),編譯器通過參數(shù)的個(gè)數(shù)及類型來區(qū)分2.輔助構(gòu)造方法不能直接構(gòu)建對(duì)象,必須直接或間接調(diào)用主構(gòu)造方法3.構(gòu)造器調(diào)用其它的構(gòu)造器,要求被調(diào)用構(gòu)造器必須實(shí)例:/chapter6/Test04.scala
6.2.6 構(gòu)造器參數(shù)
說明:1.未使用任何修飾符,局部變量2.使用var 作為類的成員屬性使用,可以修改3.使用val 作為類只讀屬性使用,不能修改
6.4 繼承和多態(tài)
基本語法:class 子類名 extends 父類名{ 類體 }
Scala是單繼承
繼承的調(diào)用順序:先調(diào)用父類構(gòu)造器>然后子類構(gòu)造器
/*** 調(diào)用順序* 1.父類的主構(gòu)造器被調(diào)用* 2.子類的主構(gòu)造器被調(diào)用* 3.子類的輔助構(gòu)造器被調(diào)用*/
子類中如果要覆蓋父類中的屬性和方法,必須要加override關(guān)鍵字
在scala中,屬性和方法都是動(dòng)態(tài)綁定的
6.5 抽象類
6.5.1 抽象屬性和抽象方法
1.基本語法定義抽象類abstract class Person{}//通過關(guān)鍵字abstract標(biāo)記抽象類定義抽象屬性 var|val name:String//一個(gè)屬性沒有初始化,就是抽象屬性定義抽象方法def hello():String //只聲明而沒有實(shí)現(xiàn)的方法,就是抽象方法說明:只要存在抽象屬性和抽象方法,那么這個(gè)類必須定義為抽象類定義了一個(gè)抽象類,可以不定義任何的抽象屬性和方法需要子類具體化之后創(chuàng)建 對(duì)象才可用
2.繼承&重寫如果父類為抽象類,那么子類需要將抽象的屬性和方法實(shí)現(xiàn),否則子類也需要聲明為抽象類重寫非抽象方法血藥用override修飾,抽血抽象方法則可以不加override子類調(diào)用父類的方法使用super關(guān)鍵字子類對(duì)抽象屬性進(jìn)行實(shí)現(xiàn),父類抽象屬性可以用var修飾子類對(duì)非抽象屬性重寫,父類非抽象屬性只支持val類型,而不支持var因?yàn)関ar修飾的為可變變量,子類繼承之后就可以直接使用,沒必要重寫
6.5.2 匿名子類
說明:和Java一樣,可以通過包含帶有定義或重寫的代碼塊的方式創(chuàng)建一個(gè)匿名的子類
6.6 單例對(duì)象
scala語言是完全面向?qū)ο蟮恼Z言,所以并沒有靜態(tài)的操作,也沒有靜態(tài)的概念。
但是為了能夠和Java語言交互,就產(chǎn)生了一種特殊的對(duì)象來模擬類對(duì)象,稱為單例對(duì)象。
若單例對(duì)象名與類名一致,則稱該單例對(duì)象這個(gè)類的伴生對(duì)象
這個(gè)類的所有靜態(tài)內(nèi)容都可以放置在它的伴生對(duì)象中聲明
對(duì)于object定義的對(duì)象,全局只有一份,在底層,編譯后生成兩個(gè)字節(jié)碼文件
6.6.1 單例對(duì)象語法
object Person{val contry:String="china"
}
說明單例對(duì)象采用object關(guān)鍵字聲明
6.6.2 apply方法
6.7 特質(zhì)(trait)
6.7。1 特質(zhì)聲明
6.7。2 特質(zhì)疊加
6.7。3 特質(zhì)疊加執(zhí)行順序
6.7。4 特質(zhì)自身類型
6.7。5 特質(zhì)和抽象類的區(qū)別
6.8 擴(kuò)展
總結(jié)
- 上一篇: 如何在嵌入式fpga系统下关闭pcap打
- 下一篇: 小程序在安卓手机时间格式显示英文的坑