Kotlin函数声明:
private fun testFunction(funName: String = 'test function'): Unit {
println('test Function' + funName)
}
其中函数可见性修饰符默认public,public函数可以省略修饰符。
函数声明关键字`fun`必须。
函数名`testFunction `必须。
Unit函数:
函数默认值参数funName和参数类型String。
Unit作为Kotlin中的特殊的函数类型,相当于其它语言中的void函数,函数中没有return关键字,那么此函数就是Unit函数,函数返回Unit,但函数没有任何返回值。
与viod不同,viod不返回任何内容。而Unit则可以和其它一些类型进行交互
fun main() {
val name = "--- Kotlin ---- "
val testUnit : () -> Unit = {
println("!testUnit function!")
}
println(name + testUnit())
}
上面匿名函数运行后返回
!testUnit function!
--- Kotlin ---- kotlin.Unit
不会报错。
Nothing函数:
同样还有其它不会返回任何值的函数,比如Nothing函数
与Unit函数不同,Nothing意味着函数不会执行成功,,它要么抛出异常,要么因为其它原因导致程序不会回到函数调用处。
通常用于异常处理。
public inline fun TODO():Nothing = throw Error()
函数重载:
函数可以在同一个类或子类及其父类中定义多个同名函数
fun main() {
val funNumber = 2
val funName = "funName"
testFunction()
testFunction(funName)
testFunction(funName, funNumber)
}
public fun testFunction(): Unit {
println("test Function")
}
public fun testFunction(funName: String) {
println("test function " + funName)
}
public fun testFunction(funName: String, funNumber: Number) {
println("test function $funName $funNumber")
}
同过传递不同参数调用不同testFunction函数。
单表达式函数:
单表达式的特殊写法
fun main() {
testFunction()
println( testAddOperatorFunction(3, 2) )
}
fun testFunction(): Unit = println("test Function")
fun testAddOperatorFunction(num1:Int,num2:Int) = num1 + num2
假如函数只有一个表达式语句,或者只有一条求值语句,那么函数的返回类型、花括号、返回语句都可以省略。
匿名函数:
fun main() {
//匿名函数1
println({" Hello World "}())
//匿名函数2
val testUnit : () -> Unit = {
println("!testUnit function!")
}
testUnit()
}
匿名函数定义就是把程序语句放在`{}`中,匿名函数后面使用`()`表示执行函数调用。
定义变量时,实在变量后面跟上冒号和类型,而testUnit : () -> Unit 则表示任何空不需要参数并返回Unit类型的函数都可以赋值给testUnit
it关键字:
定义只有一个参数的匿名函数时,可以使用it关键字
val testUnit : (String) -> Unit = {
println("$it !testUnit function!")
}
testUnit("hello")
但如果匿名函数有多个参数,那么it关键字就不能用了。
val testUnit : (String, Int) -> Unit = { UserName, Number ->
println("$UserName, $Number !testUnit function!")
}
testUnit("hello", 666)
lambda表达式:
lambda表达式属于匿名函数的一种,
{x: Int, y:Int -> x + y}
lambda表达式始终被“{}"包围,->"左边为函数参数,右边是函数体。
lambda可以作为参数到处传递
println({title:String, descript:String -> " Hello World $title $descript"}("Lambda", "表达式"))
fun main() {
//作为参数传递
testLambda({title:String, descript:String -> " Hello World $title $descript"})
}
fun testLambda(olambda: (title:String, description:String) -> Unit) {
val title = "lambda";
val description = "表达式"
println(olambda(title, description))
}
如果一个函数的lambda参数排在最后,或者是唯一参数,那么括lambda参数的小括号就可以省略
fun main() {
//简略语法
testLambda {title:String, descript:String -> "Hello $title $descript" }
}
函数内联(inline):
在JVM上,lambda是以对象实例的形式存在,因此,JVM会为所有lambda打交道的变量分配内存。并且,lambda的内存开销非常影响性能。
而kotlin提供一种叫做“内联”的机制解决lambda引起的内存消耗,有了内联,JVM就不再需要使用lambda对象实例。
使用函数内联,只需要以inline标记使用lambda函数的函数即可:
fun main() {
//简略语法
testLambda {title:String, descript:String -> "Hello $title $descript" }
}
//函数内联
//使用inline标记函数
inline fun testLambda(olambda: (title:String, description:String) -> String) {
val title = "lambda";
val description = "表达式"
println(olambda(title, description))
}
需要注意的是,使用lambda的递归函数无法内联。
函数引用:
除了lambda表达式,kotlin还允许使用传递函数引用。
函数引用可以把一个具名函数转换成一个值参,凡是使用lambda表达式的地方,都可以使用函数引用:
fun main() {
//使用操作符::将具名函数作为参数传递
testLambda(::printCurrentYear) {title:String, descript:String -> "Hello $title $descript" }
}
inline fun testLambda(printYear: KFunction1<String, Unit>, olambda: (title:String, description:String) -> String) {
val title = "lambda";
val description = "表达式"
printYear(title)
println(olambda(title, description))
}
fun printCurrentYear(userName: String) {
print("$userName 2024 \n")
}