kotlin是Java最好的语法糖
高阶函数
函数是对过程的抽象,普通函数有一个限定条件是函数的参数和返回值必须是具体的类型,而高阶函数则去处了这个限定条件,允许函数的参数和返回值是函数类型。
fun build(test: ()-> String){
test()
}
上述kotlin代码中build方法允许传入一个()->String的函数类型,那么kotlin是怎么实现该功能的呢?反编译为Java方法如下
public final void build(@NotNull Function0 test) {
Intrinsics.checkParameterIsNotNull(test, "test");
test.invoke();
}
该Function0接口如下
/** A function that takes 0 arguments. */
public interface Function0<out R> : Function<R> {
/** Invokes the function. */
public operator fun invoke(): R
}
可以发现,实际上对应的java方法是通过传递一个Function0的接口,并在方法中调用接口invoke方法来实现的。
扩展函数
在Java中,扩展某个类或者对象的能力,一般会使用继承或者代理或者装饰器等方式来实现,而kotlin在语法层面就实现了。比如给String类扩展一个test方法,
fun String.test():String{
return "test"
}
在使用时可以直接调用"aa".test(),那么kotlin是怎么实现的呢?反编译代码可以看到起对应的Java代码如下
@NotNull
public final String test(@NotNull String $this$test) {
Intrinsics.checkParameterIsNotNull($this$test, "$this$test");
return "test";
}
因为我是直接将扩展函数放在具体的kotlin类中,所以其在该类生成了第一个参数为String的public final方法,可以看到,kotlin的扩展函数实际上时通过语法糖的形式自动生成方法,而没有修改字节码,也不会造成性能开销。
Lambda表达式
Lambda表达式也是一种语法糖,而且和高阶函数还不太好区分,一般而言,高阶函数必须用->来隔离函数参数和参数返回值,而Lambda表达式必须用{}包裹,如下我们在kotlin文件中申明了如下Lambda表达式
val bds = { x: Int ->
val y = x + 1
y
}
上述我们定义了一个Lambda表达式,作用是给每个参数的值加1并返回,调用的方式如下:
fun String.test():String{
return "adad" + bds(1)
}
上述我们定义了一个扩展函数,在扩展函数中调用了bds这个lambda表达式,那么Lambda表达式这个语法糖是如何工作的呢?我们来看一下反编译成Java的代码
@NotNull
private static final Function1 bds;
@NotNull
public static final String test(@NotNull String $this$test) {
Intrinsics.checkParameterIsNotNull($this$test, "$this$test");
return "adad" + ((Number)bds.invoke(1)).intValue();
}
@NotNull
public static final Function1 getBds() {
return bds;
}
static {
bds = (Function1)null.INSTANCE;
}
可以从代码中看到,bds变量被申明为Function1接口,在static块中初始化,而test高阶函数中是通过调用bds的invoke方法来获取返回值的。看上去,Lambda表达式和扩展函数有类似的实现原理,都是基于FunctionN(N表示数字)接口来实现。如果了解Java中Lambda的实现,你会发现其实很相似。