注册

那些隐藏在项目中的kotlin小知识,在座各位...

写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替换

这也是高阶函数得以实现的根本原因


作者:小松漫步
链接:https://juejin.cn/post/7256985832313094204
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册