写kotlin越来越久,很多代码虽然能看懂,并且能去改,但是不知道他用了啥,里面的原理是什么,举个例子?大家一起学习一下吧
内联函数
顾名思义,但是在项目中我遇到得很少,他比较适用于一些包装方法的写法,比如下面这个
inline fun measureTimeMillis(block: () -> Unit): Long {
val startTime = System.currentTimeMillis()
block()
return System.currentTimeMillis() - startTime
}
val time = measureTimeMillis {
// code to be measured here
}
println("Time taken: $time ms")
这样的函数,以后如果想要测一段代码的运行时间,只需要将measureTimeMillis包着他就行
类型别名
一个很神奇的东西,允许为现有类型定义新名称
data class Person(val name: String, val age: Int)
typealias People = List<Person>
val people: People = listOf(
Person("Alice", 25),
Person("Bob", 30),
Person("Charlie", 35)
)
fun findOlderThan(people: People, age: Int): People {
return people.filter { it.age > age }
}
fun main() {
val olderPeople = findOlderThan(people, 30)
println(olderPeople)
}
其中People就是一个别名,如果使用typealias替代直接定义list,项目中就会少很多后缀为list的列表,少了类似于personlist这种变量,在搜索,全局替换,修改时也会更加直观看到person和people的区分场景
typealias可以被大量使用在list, map乃至于函数中,因为这些命名可能会比较长,替换后可以提高可读性
高阶函数
一个一开始很难理解,理解后又真香的函数,我愿称理解的那一刻为程序员进阶闪耀时,当一个老程序员回首往事时,他不会因为虚度年华而悔恨,但是一定会因为不懂高阶函数而羞耻
尤其是在项目中发现这种函数,又看不懂时,是万万不敢问同事的,所以,请现在就了解清楚吧
fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
return operation(x, y)
}
fun main() {
val sum = calculate(10, 5) { x, y -> x + y }
println("Sum is $sum")
val difference = calculate(10, 5) { x, y -> x - y }
println("Difference is $difference")
}
可以看到,calculate其实并没有做什么,只是执行了传入进来的operation,这,就是高阶函数,所谓领导也是如此,优秀的下属,往往将方案随着问题传入进来,领导只要批示一下执行operation即可
配合上lambda原则,最后一个参数可以提出到括号外面,也就是讲operation提出到外面的{}中,交给调用方自己执行,就形成了这样的写法
val sum = calculate(10, 5) { x, y -> x + y }
理解这一点后,一下子就清晰了很多,calculate看起来什么都没做,他却成为了世界上功能最强大,最灵活,bug最少的计算两个数运算结果的函数
深入
了解上面分析,已经足够我们在kotlin项目中进阶了,现在,我们来看下高阶函数反编译后的java代码
public final class TestKt {
public static final int calculate(int x, int y, @NotNull Function2 operation) {
Intrinsics.checkNotNullParameter(operation, "operation");
return ((Number)operation.invoke(x, y)).intValue();
}
public static final void main() {
int sum = calculate(10, 5, (Function2)null.INSTANCE);
String var1 = "Sum is " + sum;
System.out.println(var1);
int difference = calculate(10, 5, (Function2)null.INSTANCE);
String var2 = "Difference is " + difference;
System.out.println(var2);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
}
虽然java的实现太不优雅,但是我们可以看出,高阶函数,本质上传入的函数是一个名为Function2的对象,
public interface Function2<in P1, in P2, out R> : Function<R> {
/** Invokes the function with the specified arguments. */
public operator fun invoke(p1: P1, p2: P2): R
}
他是kotlin包自带的函数,看起来可以用来在反编译中替换匿名lambda表达式,将其逻辑移动到自身的invoke中,然后生成一个Function2对象,这样实现kotlin反编译为java时的lambda替换
这也是高阶函数得以实现的根本原因