注:编码工具为IntelliJ
目录
匿名函数入门示例
fun main() {
val len = "KimuraTakuya".count { it == 'a' }
println(len)
}
输出:
3
示例中的{it == 'a'}就是一个匿名函数。
匿名函数只有参数列表和函数体,没有函数名。
匿名函数可以作为另一个函数的实际参数或者返回值。
匿名函数==lambda表达式。
函数类型和隐式返回
Kotlin中可以定义函数类型的变量,该变量可以作为函数使用,通过()或者invoke()调用。
隐式返回:函数类型的实现即匿名函数中的返回值不能用return关键字修饰,函数体的最后一句的执行结果即为返回值。
package step_two
fun main() {
// ()->Int 是函数类型
// 等号后{}中的内容是函数的实现
val f: ()->Int = {
println("in Anonymous func")
18
}
println(f())
println(f.invoke())
}
输出:
in Anonymous func
18
in Anonymous func
18
定义函数类型变量的两种方式
方式一:
package step_two
fun main() {
val func: (Int, Int) -> Int = {a, b -> a + b}
println(func(12, 11))
}
输出:
23
方式二:
package step_two
fun main() {
val func = { a: Int, b: Int -> a + b }
println(func(12, 11))
}
输出:
23
方式二,编译器会根据匿名函数体的最后一句执行结果推断返回值类型。
函数类型作为函数参数
类似于Java中的回调接口。
非内联函数
反编译为Java代码显示,将作为函数参数的函数定义成了一个对象,效率低。
package step_two
fun main() {
login("abc", "123"){
msg, code -> println("login result: msg = $msg, code = $code")
}
}
fun login(user: String, pwd: String, result:(String, Int) -> Unit){
if("abc" == user && "123" == pwd)
{
result("success", 200);
}else{
result("failure", 400);
}
}
输出:
login result: msg = success, code = 200
反编译后的Java代码:
package step_two;
import kotlin.Metadata;
import kotlin.jvm.functions.Function2;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
@Metadata(
mv = {1, 5, 1},
k = 2,
d1 = {"\u0000\u001c\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0002\u0010\b\n\u0002\b\u0002\u001a0\u0010\u0000\u001a\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u00032\u0006\u0010\u0004\u001a\u00020\u00032\u0018\u0010\u0005\u001a\u0014\u0012\u0004\u0012\u00020\u0003\u0012\u0004\u0012\u00020\u0007\u0012\u0004\u0012\u00020\u00010\u0006\u001a\u0006\u0010\b\u001a\u00020\u0001¨\u0006\t"},
d2 = {"login", "", "user", "", "pwd", "result", "Lkotlin/Function2;", "", "main", "kt"}
)
public final class FuncAsFuncParamKt {
public static final void main() {
login("abc", "123", (Function2)null.INSTANCE);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
public static final void login(@NotNull String user, @NotNull String pwd, @NotNull Function2 result) {
Intrinsics.checkNotNullParameter(user, "user");
Intrinsics.checkNotNullParameter(pwd, "pwd");
Intrinsics.checkNotNullParameter(result, "result");
if (Intrinsics.areEqual("abc", user) && Intrinsics.areEqual("123", pwd)) {
result.invoke("success", 200);
} else {
result.invoke("failure", 400);
}
}
}
内联函数
用inline关键字修饰的函数。当函数参数中含有函数时,将该函数定义为内联函数,反编译为Java代码后显示将内联函数的实现直接拷贝到了函数调用处,减少了函数的入栈出栈,效率高。
package step_two
fun main() {
login("abc", "123"){
msg, code -> println("login result: msg = $msg, code = $code")
}
}
inline fun login(user: String, pwd: String, result:(String, Int) -> Unit){
if("abc" == user && "123" == pwd)
{
result("success", 200);
}else{
result("failure", 400);
}
}
输出:
login result: msg = success, code = 200
反编译后的Java代码:
package step_two;
import kotlin.Metadata;
import kotlin.jvm.functions.Function2;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
@Metadata(
mv = {1, 5, 1},
k = 2,
d1 = {"\u0000\u001c\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0002\u0010\b\n\u0002\b\u0002\u001a6\u0010\u0000\u001a\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u00032\u0006\u0010\u0004\u001a\u00020\u00032\u0018\u0010\u0005\u001a\u0014\u0012\u0004\u0012\u00020\u0003\u0012\u0004\u0012\u00020\u0007\u0012\u0004\u0012\u00020\u00010\u0006H\u0086\bø\u0001\u0000\u001a\u0006\u0010\b\u001a\u00020\u0001\u0082\u0002\u0007\n\u0005\b\u009920\u0001¨\u0006\t"},
d2 = {"login", "", "user", "", "pwd", "result", "Lkotlin/Function2;", "", "main", "kt"}
)
public final class FuncAsFuncParamKt {
public static final void main() {
String user$iv = "abc";
String pwd$iv = "123";
int $i$f$login = false;
short code;
String msg;
boolean var5;
String var6;
boolean var7;
if (Intrinsics.areEqual("abc", user$iv) && Intrinsics.areEqual("123", pwd$iv)) {
code = 200;
msg = "success";
var5 = false;
var6 = "login result: msg = " + msg + ", code = " + code;
var7 = false;
System.out.println(var6);
} else {
code = 400;
msg = "failure";
var5 = false;
var6 = "login result: msg = " + msg + ", code = " + code;
var7 = false;
System.out.println(var6);
}
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
public static final void login(@NotNull String user, @NotNull String pwd, @NotNull Function2 result) {
int $i$f$login = 0;
Intrinsics.checkNotNullParameter(user, "user");
Intrinsics.checkNotNullParameter(pwd, "pwd");
Intrinsics.checkNotNullParameter(result, "result");
if (Intrinsics.areEqual("abc", user) && Intrinsics.areEqual("123", pwd)) {
result.invoke("success", 200);
} else {
result.invoke("failure", 400);
}
}
}
函数引用
用::函数名的形式,可以引用一个现有的符合条件的函数作为另一个函数实际参数。
package step_two
fun plus(a: Int, b: Int) {
println("a + b = ${a + b}")
}
fun minus(a: Int, b: Int){
println("a - b = ${a - b}")
}
fun calc(a: Int, b: Int, cal: (Int, Int) -> Unit) {
cal(a, b)
}
fun main() {
calc(99, 13, ::plus)
val method = ::minus
calc(10000, 1, method)
}
输出:
a + b = 112
a - b = 9999
函数类型作为函数的返回值
package step_two
fun main() {
generateFunc("hello anonymous function")("this is another func")
}
fun generateFunc(msg: String): (String) -> Unit {
println(msg)
return { str: String -> println(str) }
}
输出:
hello anonymous function
this is another func