1搏予、面向?qū)ο缶幊毯秃瘮?shù)式編程
2点把、函數(shù)定義格式
def 函數(shù)名 ([參數(shù)名: 參數(shù)類型], ...)[[: 返回值類型] =] {
語句... //完成某個功能
return 返回值
}
def test(s:String) : String ={
return "abc"
}
3借宵、函數(shù)的各種簡化和變形
1) 省略return (方法體內(nèi)最后一行為返回的值)
def test1(s:String) : String ={
"abc"
}
println(test1("a")) // abc
2) 省略返回值類型(scala會自動判斷最后一行值的類型)
def test2(s:String) ={
"abc"
}
println(test2("a")) // abc
3) 省略入?yún)?/strong>
def test3() ={
"abc"
}
println(test3()) // abc
4)省略大括號()當方法體內(nèi)只有一行代碼時幌衣,可以省略{ }
def test4() ="abc"
println(test4()) // abc
5)省略小括號 當方法沒有入?yún)r,可以省略()
def test5 = "abc"
println(test5) // abc 若方法省了小括號壤玫,在調(diào)用時也可以省略小括號
def test5 = "abc"
val ssss = "abc"
方法和變量只有關(guān)鍵字不一樣
6)補充
- 方法省略等號豁护,返回值為Unit
def test6(){
"abc"
}
println(test6()) // ()
- 方法體沒有返回值是Unit,
只要定義的返回值時Unit,不管方法體最后一行是什么都會返回Unit
//方法體沒有返回值是Unit,
// 要定義的返回值時Unit,不管方法體最后一行是什么都會返回Unit類型
def test1(s:String) : Unit ={
}
def test2(s:String) : Unit ={
"abc"
}
println(test1("a")) // ()
println(test2("a")) // ()
- 7)可變參
def test7(s:String*)={
for(i<- s){
println(i)
}
}
test7("張三","里斯") //張三
//里斯
4哼凯、Scala是完全面向函數(shù)的語言
注意:
函數(shù)的類型:() => Int、Int => Int 楚里、(Int) = >Int等
1)函數(shù)可以賦值給變量
2)函數(shù)可以作為函數(shù)的參數(shù)
def f5(f6 : () => Int): Int ={
f6()+10
}
def f(): Int ={
5
}
println(f5(f)) //15
簡化(匿名函數(shù))
def f5(f6 : () => Int): Int ={
f6()+10
}
println(f5(()=>{5})) //15
val a = ()=>{"a"}
println(a) // <function0>
println(a()) // a
匿名函數(shù)加強(匿名函數(shù)傳遞的是一段邏輯)
def f7(f : (Int) => Unit) : Unit = {
f(10)
}
f7((i) => {println(i)}) //10
f7((i) => println(i)) //10
f7(i => println(i)) //10
f7(println(_)) //10
def f8(f:(Int,Int) => Int): Int = {
f(10,10)
}
println(f8((x:Int,y:Int) => {x+y})) // 20
println(f8((x,y) => { x+y })) // 20
println(f8((x,y) => x+y)) // 20
println(f8(_+_)) // 20
3)函數(shù)可以作為函數(shù)的返回值
def f()={
"scala"
}
def f1() ={
f //當方法沒有入?yún)r挡逼,調(diào)用時可以省略小括號
}
println(f1()) // scala
println(f1()()) // 直接提示錯誤
def f()={
"scala"
}
def f1() ={
f _ // 有 _ 返回才是函數(shù),而不是值
}
println(f1()) // <function0>
println(f1()()) // scala
解釋:一般情況下腻豌,f標識傳遞引用家坎,f()表示實際調(diào)用
f _ :中的 _ 如果不寫返回值并不是一個函數(shù),而是f函數(shù)的返回值吝梅。在函數(shù)f1中虱疏,函數(shù)f也會執(zhí)行(因為無參函數(shù)調(diào)用,可以省略小括號)苏携。
簡化
def f1():() => String ={
def f() : String ={
"scala"
}
f _ //scala中函數(shù)哪里都寫可以做瞪,這種只是相當于把f函數(shù)寫道f1里面
}
print(f1()())
解釋:
()=>String 代表返回的是一個函數(shù),沒有入?yún)⒂叶常祷刂凳荢tring的函數(shù)
再變型
def f2(i :Int) : Int => Int ={
def f3(j:Int): Int ={
i*j
}
f3 _
}
println(f2(3)(4)) //12
注意:正常再觸發(fā)f3函數(shù)時装蓬,f2已經(jīng)彈棧,入?yún)不能再f3中拿到運用纱扭,這里有個閉包的概念牍帚。把i 的生命周期改變,就像再把i和j打成一個包乳蛾,放到f3里面
關(guān)于閉包的類比:
類似java堆棧暗赶,通常認知,方法進棧肃叶,對象進堆
1蹂随、棧上分配
public void test(){
User user = new User
//如果創(chuàng)建千萬對象,彈棧后因惭,方法之外的地方也沒有用到這些對象岳锁,則這些對象隨著方法彈棧,不進入堆中
}
2蹦魔、逃逸分析
public User test(){
User user = new User
return user
// 方法返回了對象激率,這時不在隨方法彈棧,逃逸進入堆中
}
柯里化(上面的簡化)
def f2(i:Int)(j:Int) : Int = {
i*j
}
println(f2(3)(4))
5版姑、其他知識點
- 惰性函數(shù)
def sum(i:Int,j:Int): Int ={
println("sum函數(shù)執(zhí)行了")
i+j
}
val res = sum(10,20)
println("----------x----------")
println("----------x----------")
println("----------x----------")
println(res)
結(jié)果:sum函數(shù)執(zhí)行了
----------x----------
----------x----------
----------x----------
30
lazy val res = sum(10,20)
println("*******x********")
println("*******x********")
println("*******x********")
println(res)
結(jié)果:
*******x********
*******x********
*******x********
sum函數(shù)執(zhí)行了
30
- 惰性函數(shù)加載時才執(zhí)行
- lazy不能修飾var變量
- lazy修飾函數(shù)和變量柱搜,都會導致延遲加載