1.Kotlin函数可以使用中缀表示法来调用,当满足一下条件时:
infix fun Int.add(x:Int):Int{
return this+x
}
fun printAdd(){
val value=2 add 3//中缀表示法调用add函数(不用加".")
print("the value is $value")
}
2.在Kotlin中,调用函数的时候可以使用命名的参数:
fun foo(arg1:String="Hello Kotlin",arg2:Boolean,arg3:Int){
print("arg1="+arg1+"&arg2="+arg2+"arg3="+arg3)
}
fun printFoo(){
foo(arg2 = true,arg3 = 7)//命名参数调用foo函数
}
3.Kotlin函数定义可变数量的参数,只要用vararg关键字修饰即可:
//可变数量的参数
fun foo4(vararg args:Int){
for (arg in args){
print(arg.toString()+",")
}
}
fun printFoo4(){
foo4(1,2,3,4,5)//1,2,3,4,5,
}
4.Kotlin函数以数组的内容作为参数,只要用伸展(spread)操作符(在数组前面加 *):
fun foo4(vararg args:Int){
for (arg in args){
print(arg.toString()+",")
}
}
fun printFoo4(){
val values= intArrayOf(1,2,3,4,5)
foo4(*values)//使用扩展运算符传一个数组给可变参数
}
5.高阶函数
高阶函数可以将一个函数作为参数或返回值:
fun add2(x:Int=0,y:Int=0):Int{
return x+y
}
fun operate(x:Int=0,y:Int=0,body:(Int,Int)->Int){//body是一个函数类型,传入两个Int类型参数,返回一个Int类型参数
print("this result is "+body(x,y))
}
fun getValue(){
operate(3,7,::add2)
}
6.Lambda表达式
Lambda表达式通常使用“{ }”包围,参数是定义在“()”内,实体部分跟在“->”后面;
以上的operate()方法,我们还有一个更简洁的调用方式,即传入一个lambda表达式:
operate(3,7,{x,y->x+y})//函数参数传入一个lambda表达式
当函数参数是最后函数的最后一个参数,并且你传入一个lambda表达式作为相应的参数,则可以在圆括号之外指定它:
operate(3,7){//函数参数作为函数的最后一个参数,并且传入的是一个lambda表达式,可以在在圆括号外指定
x,y->x+y
如果lambda表达式只有一个参数,kotlin可以自己计算出签名,它允许我们不声明唯一的参数,并且隐含的为我们声明其名称为it:
fun upCase(str:String,body:(String)->String):String{//body是一个函数参数,传入一个String类型参数,返回一个String类型
return body(str)
}
fun transform(){
upCase("HelloKotlin"){//函数字面值只有一个参数,可以省略参数声明,其名称是it
it.toUpperCase()
}
}
如果lambda表达式是调用的唯一参数,则调用中的圆括号可以完全省略。
7.匿名函数
匿名函数与常规函数一样,只是省略了函数名称:
fun String.upper(body:(String)->String):String{
return body(this)
}
fun transform(){
"HelloKotlin".upper { it.toUpperCase() }//lambda表达式是调用的唯一参数,则调用的圆括号可以省略
"HelloKotlin".upper(fun(str:String):String{//将匿名函数作为一个函数参数传入
return str.toUpperCase()
})
}
匿名函数 与 Lambda表示式区别:
- 匿名函数作为参数,一般定义在“()”中;而Lambda表达式可以定义到调用函数“()”外。
- 另外区别在“非局部返回(non-local returns)”行为上:非标签注解的return(返回对应的最内层的函数(即fun)),在匿名函数中,退出该匿名函数;而在Lambda表达中,退出包含该表达式的函数。
fun foo() {
ints.forEach {
if (it == 0) return//这个 return 表达式从最直接包围它的函数即 foo 中返回。
print(it)
}
}
fun transform():String{
"HelloKotlin".upper {
print(it.toUpperCase())
return@upper it.toUpperCase()//返回必须加标签限制
}
"HelloKotlin".upper(fun(str:String):String{
return str.toUpperCase()//从匿名函数返回
})
}
8.内嵌函数
作为自变量接收的函数令人讨厌的是编译器需要为它们创建类,这将影响性能。但是,这可以用保留字inline容易地解决。
由于Inline函数是在编译时将它的代码替换对它的调用,所以在性能方面影响较少。为此,它不需要用额为的对象。
我们能够转换doAsync到一个inline函数:
inline fun doAsync(crossinline f: () -> Unit) {
Thread({ f() }).start()
}
在这个例子中,由于我们从另一个执行内容(另一个Lambda表达式)中调用f(),所以要求crossinline。不用太担心这些,在需要使用它时,编译器会提醒你的。
现在,在我们的代码中,产生异步代码块:
doAsync {
op1()
op2()
op3()
}
这样在{}内的每件事都将在第二个线程中执行。