1. Scala 與 Java 的關(guān)系
Scala 和 Java 都是運(yùn)行在 JVM 上。
Scala 可以調(diào)用 Java 的類庫(kù)酬姆,在語(yǔ)法上較 Java 更為簡(jiǎn)潔
Scala 將函數(shù)式編程和面向?qū)ο笏枷胪昝赖慕Y(jié)合
2. 基本語(yǔ)法
class Hello {
/*
定義變量: val 代表常量嗜桌;var 代表變量
val/var 變量名:變量類型 = 變量值
*/
val a: Int = 1
/*
定義方法:
def 函數(shù)名(參數(shù)名:參數(shù)類型):返回值類型={方法體}
*/
def hello(arg: String): Unit = {
println(arg)
}
}
object Hello {
// Scala程序的入口
def main(args: Array[String]): Unit = {
println("hello,scala")
}
/*
完全面向?qū)ο螅簊cala 完全面向?qū)ο螅?scala 去掉了 java 中非面向?qū)ο蟮脑卮巧?static 關(guān)鍵字骨宠,void 類型
1.static
scala 無(wú) static 關(guān)鍵字,由 object 實(shí)現(xiàn)類似靜態(tài)方法的功能(類名.方法名),object 關(guān)鍵字和 class 的關(guān)鍵字定義方式相同层亿,但作用不同桦卒。class 關(guān)鍵字和 java 中的 class 關(guān)鍵字作用相同,用來(lái)定義一個(gè)類匿又;object 的作用是<front color:green>聲明一個(gè)單例對(duì)象<front color>方灾,object 后的“類名”可以理解為該單例對(duì)象的變量名。
2.void
對(duì)于無(wú)返回值的函數(shù)碌更,scala 定義其返回值類型為 Unit 類裕偿,Unit 只有一個(gè) Null 對(duì)象。
*/
}
3. 運(yùn)行原理
- object 在底層會(huì)生成兩個(gè)類
Hello
,Hello$
- Hello 中有個(gè) main 函數(shù)痛单,調(diào)用
Hello$
類的一個(gè)靜態(tài)對(duì)象MODULES$
-
Hello$.MODULES$.對(duì)象
是靜態(tài)的嘿棘,通過(guò)該對(duì)象調(diào)用Hello$
的 main 函數(shù) - 在 main 中寫(xiě)的代碼在放在
Hello$
的 mian 中,Scala 編譯器在底層做了包裝 - Scala 程序的執(zhí)行入口時(shí) object 中的 mian() 函數(shù)
/* Hello 源代碼 */
object Hello {
def main(args: Array[String]): Unit = {
//4. 可以理解我們?cè)?main 中寫(xiě)的代碼在放在 Hello$ 的 main,在底層執(zhí)行 scala 編譯器做了一個(gè)包裝
println("hello,scala")
}
}
//1. object 在底層會(huì)生成兩個(gè)類 Hello , Hello$
/* Hello.class 類 */
//2. Hello 中有個(gè) main 函數(shù)桦他,調(diào)用 Hello$ 類的一個(gè)靜態(tài)對(duì)象 MODULES$
public final class Hello
{
public static void main(String[] paramArrayOfString)
{
Hello$.MODULE$.main(paramArrayOfString);
}
}
/* Hello$.class 類 */
public final class Hello$
{
public static final MODULE$;
static { new (); }
public void main(String[] args)
{
//3. Hello$.MODULE$. 對(duì)象是靜態(tài)的,通過(guò)該對(duì)象調(diào)用 Hello$ 的 main 函數(shù)
Predef..MODULE$.println("hello,scala");
}
private Hello$()
{
MODULE$ = this;
}
}
說(shuō)明:
- Scala 中如果使用 object 關(guān)鍵字聲明類谆棱,在編譯時(shí)會(huì)同時(shí)生成兩個(gè)類:
當(dāng)前類
快压,當(dāng)前類$
- 使用
當(dāng)前類$
的目的在于模擬靜態(tài)語(yǔ)法,可以通過(guò)類名直接訪問(wèn)方法垃瞧。 - Scala 將
當(dāng)前類$
這個(gè)對(duì)象稱之為“伴生對(duì)象”蔫劣,伴隨著類所產(chǎn)生的對(duì)象,這個(gè)對(duì)象中的方法可以直接使用个从。
總結(jié):object 對(duì)象名 中的 mian() 方法就是對(duì)象名$
中的MODULES$
的 mian()
4. 字符串輸出
4.1 格式化輸出 printf
字符串脉幢,通過(guò) % 傳值。
val a = 10
// 格式化輸出
printf("a的值是: %d %.2f %s", a, 2.888, "abc")
a的值是: 10 2.89 asc
4.2 模板輸出
三重引號(hào)中間可以使用模板輸出嗦锐,方便多行帶縮進(jìn)的代碼嫌松,方便 SQL
val s =
"""
|select
| name,
| age,
| gender
|from user
|where name='zhangsan';
""".stripMargin
print(s)
4.3 字符串變量賦值輸出
可以使用 ${變量} 的形式傳值,{ } 內(nèi)也可以進(jìn)行計(jì)算
val name = "zhangsan"
val age = 20
val b =
s"""
|select
| name,
| age,
| gender
|from user
|where name='${name}' and age=${age + 2};
""".stripMargin
println(b)
5. 鍵盤(pán)輸入
三種常用的輸入奕污,Stdln.readLine萎羔、Stdln.readShort、Stdln.readDouble
//1. 輸入姓名
val name = StdIn.readLine("請(qǐng)輸入姓名")
//2. 輸入年齡
print("請(qǐng)輸入年齡:")
val age = StdIn.readShort()
//3. 輸入薪水
print("請(qǐng)輸入薪水:")
val salary = StdIn.readDouble()
6.數(shù)據(jù)類型
基本數(shù)據(jù)類型
- Scala 中一切數(shù)據(jù)都是對(duì)象碳默,都是 Any 的子類
- Scala 中數(shù)據(jù)類型分為兩大類:數(shù)值類型(AnyVal)贾陷、引用類型(AnyRef),這兩種類型都是對(duì)象
- Scala 數(shù)據(jù)類型遵循低精度向高精度自動(dòng)轉(zhuǎn)換(隱式轉(zhuǎn)換)
- Scala 特殊的類型之 Null嘱根,它只有一個(gè)實(shí)例就是 null髓废,它是所有引用類型的(AnyRef) 的子類
- Boolean:true / false
- Unit 類型:無(wú)值,和 java 中 void 等同该抒。用作不返回任何結(jié)果的方法的結(jié)果類型慌洪。Unit 只有一個(gè)實(shí)例值,寫(xiě)成 ()
- ?StringOps 類型:對(duì) Java 中 String 類型的擴(kuò)展
- Nothing 類型:Nothing 類型在 Scala 的類層級(jí)的最低端;它是任何其他類型的子類型蒋譬。當(dāng)一個(gè)函數(shù)割岛,我們確定沒(méi)有正常的返回值,可以用 Nothing 來(lái)指定返回類型(聯(lián)想 java 的多態(tài))犯助,這樣可以把返回的值(異常)賦給其它的函數(shù)或者變量(兼容性)
7. 類型轉(zhuǎn)換
自動(dòng)類型轉(zhuǎn)換
強(qiáng)制類型轉(zhuǎn)換
將精度大的數(shù)值類型轉(zhuǎn)換為精度小的數(shù)值類型癣漆。使用時(shí)要加上強(qiáng)制轉(zhuǎn)函數(shù),但可能造成精度降低或溢出剂买,格外要注意惠爽。
// Char類型可以保存Int的常量值,但不能保存Int的變量值瞬哼,需要強(qiáng)轉(zhuǎn)
var c2: Char = 98 // 正確婚肆,因?yàn)橹苯訉⒁粋€(gè)數(shù)值給char,編譯器只判斷是否越界
var c3: Char = 'a' + 1 // 錯(cuò)誤坐慰,Int高->char低较性,編譯器判斷類型
var c4: Char = ('a' + 1).toChar // 正確,先提升成 Int结胀,在強(qiáng)轉(zhuǎn)成 Cahr赞咙,輸出 b
// Byte和Short類型在進(jìn)行運(yùn)算時(shí),當(dāng)做Int類型處理糟港。
var a : Short = 5
a = a-2 // 錯(cuò)誤攀操, Int->Short
var b : Byte = 3
b = b + 4 // 錯(cuò)誤,Int->Byte
8. 運(yùn)算符
- 對(duì)于除號(hào)“/”秸抚,它的整數(shù)除和小數(shù)除是有區(qū)別的:整數(shù)之間做除法時(shí)速和,只保留整數(shù)部分而舍棄小數(shù)部分。
var r1: Int = 10 / 3 // 3
println("r1=" + r1)
var r2: Double = 10 / 3 // 3.0
println("r2=" + r2)
var r3: Double = 10.0 / 3 // 3.3333
println("r3=" + r3)
println("r3=" + r3.formatted("%.2f")) // 保留小數(shù)點(diǎn)2位剥汤,使用四舍五入
- 在做比較時(shí) == 的作用和 java 中的 .equals() 方法類似颠放,而 = 則更多的是使用 .eq 來(lái)操作
- Scala 中沒(méi)有++、--操作符吭敢,需要通過(guò) +=慈迈、-= 來(lái)實(shí)現(xiàn)同樣的效果
- 本質(zhì)上 Scala 中沒(méi)有任何的運(yùn)算符,因?yàn)樗械倪\(yùn)算符都是函數(shù)
9. 流程控制
9.1 if else
if else 語(yǔ)句和 java 類似省有,但是痒留,Scala 中 if else 是有返回值的,返回值取決于滿足條件的代碼體的最后一行內(nèi)容蠢沿。
Scala 沒(méi)有 switch case 結(jié)構(gòu)伸头,有一種更強(qiáng)大的結(jié)構(gòu)(模式匹配)。
9.2 for 遍歷
// 1.前閉后閉舷蟀,i 從1循環(huán)到3
for(i <- 1 to 3){
print(i + " ")
}
1 2 3
// 2.前閉后開(kāi)恤磷,i 從1循環(huán)到2
for(i <- 1 until 3){
print(i + " ")
}
1 2
// 3.循環(huán)守衛(wèi)面哼,加入條件 if i != 3,當(dāng)i不等于3時(shí)滿足條件扫步,即輸出時(shí)跳過(guò)3魔策,類似于 java 中的 continue
for (i <- 1 until 10 if i != 3) {
print (i + " ")
}
1 2 4 5 6 7 8 9
// 4.循環(huán)步長(zhǎng),by 表示步長(zhǎng)
for (i <- 1 to 10 by 2) {
print(i +" ")
}
1 3 5 7 9
// 5.嵌套循環(huán)河胎,注意此處沒(méi)有關(guān)鍵字闯袒,所以范圍后要加;來(lái)隔斷邏輯
// 注意:只有當(dāng)所有的邏輯在內(nèi)循環(huán)中,才可以將兩個(gè)循環(huán)成一個(gè)for
for (i <- 1 to 2; j <- 1 to 3) {
println("i=" + i + "j=" + j)
}
i=1j=1
i=1j=2
i=1j=3
i=2j=1
i=2j=2
i=2j=3
// 6.引入變量
// 引入變量
for (i <- 1 to 3; j = 4 - i) {
println("i=" + i + "j=" + j)
}
i=1j=3
i=2j=2
i=3j=1
// 7.循環(huán)返回值游岳,將循環(huán)中的所有值*2政敢,并將結(jié)果返回到新的集合中
val res = for(i <- 1 to 10) yield {
i * 2
}
println(res)
9.3 While 循環(huán)
while 語(yǔ)句沒(méi)有返回值,即整個(gè) while 語(yǔ)句的結(jié)果是 Unit 類型 ()
// while 循環(huán)與 java 中類似
var i = 0
while (i < 10) {
println(i+" ")
i += 1
}
注:因?yàn)?while 中沒(méi)有返回值胚迫,所以當(dāng)要用該語(yǔ)句來(lái)計(jì)算并返回結(jié)果時(shí)喷户,就不可避免的使用變量,而變量需要聲明在 while 循環(huán)的外部访锻,那么就等同于循環(huán)的內(nèi)部對(duì)外部的變量造成了影響褪尝,也就違背了函數(shù)式編程的重要思想(輸入=>函數(shù)=>輸出,不對(duì)外界造成影響)期犬,所以不推薦使用河哑,而是 推薦使用 for 循環(huán)
9.4 循環(huán)終止
Scala 為更好的適應(yīng)函數(shù)式編程,使用 breakable() 方法和 break() 方法控制結(jié)構(gòu)來(lái)實(shí)現(xiàn) break 和 continue 功能哭懈。
Scala 的循環(huán)終止灾馒,本質(zhì)上是用拋異常的并捕獲異常的方式 解決的茎用,分別用 break() 方法拋異常遣总,用 breakable() 方法捕獲
import util.control.Breaks._
// 實(shí)現(xiàn) break 功能
var i = 0
breakable {
while (i < 10) {
println("i=" + i)
i += 1
if (i == 5) break()
}
}
// 實(shí)現(xiàn) continue 功能
var j = 0
while (j < 10) {
breakable {
j += 1
if (j == 5) break()
println("j=" + j)
}
}
注:break:breakable 放在循環(huán)外;continue:breakable 放在循環(huán)內(nèi)