聊聊Kotlin中的lambda

简介: 聊聊Kotlin中的lambda

聊聊Kotlin中的lambda

本质

kotlin中的lambda使用创建类和调用类实现。

实现原理

将lambda定义的方法变成一个function类,其invoke方法体内容也就是lambda的方法体。

在lambda执行的时候会创建这个function类再调用其invoke方法实现。

代码演示

fun main(args: Array<String>) {    
    foo {         
       println("dive into Kotlin...")     
     } 
} 
fun foo(block: () -> Unit) { 
    println("before block")     
    block()    
     println("end block") 
}

foo函数使用了Lambda表达式,所以我们来看下foo函数反编译后的字节码文件:

public static final void main(@NotNull String[] args) { 
    Intrinsics.checkParameterIsNotNull(args, "args");     
    //可以看到Lambda表达式变成了创建一个Function0类并传入方法中
    foo((Function0)null.INSTANCE); 
} 
  //该方法参数变成了一个Function类
public static final void foo(@NotNull Function0 block) {     
  Intrinsics.checkParameterIsNotNull(block, "block");     
  String var1 = "before block";     
  System.out.println(var1);     
  //调用invoke方法也就是Lambda中的方法体
  block.invoke();     
  var1 = "end block";     
  System.out.println(var1);
}

缺点

这种方法如果放在多个中间操作符使用lambda的时候会非常耗费性能。

ps:因为中间操作符大多使用lambda表达式,是因为它够简单易懂,当调用个lambda表达式时也就会对应的创建多个Functon类和调用其invoke方法

优化方案

java的Lambda背景

java中为什么没有用这种方式实现呢:创建类调用其invoke方法。

其实java中是通过invokedynamic指令实现的,其本质是运行时进行替换对应的Lambda中的代码

好处

1.运行时替换,相比较Kotlin直接写死创建类的方式性能更好

2.在class文件中只有这个指令,不像kotlin需要设置很多不必要的信息

Kotlin的优化

为什么不去直接使用java的那个指令呢?

原因很简单,Kotlin是基于java 6开发的,而java的这个优化是在java 7才出现的,所以为了兼容只能另辟蹊径。

虽然无法实现,但是我们可以借鉴java中的做法对吧?

他是运行时进行替换方法的,所以本质是替换方法。也就是改变思路:之前我们是将表达式封装到一个类的方法中,具体调用lambda的时候调用这个类的方法 把它换成 我们直接把lambda中的方法体复制到调用方的方法体里面

java是运行时替换,我们直接编译期间就替换了,一样的效果,而且kotlin把替换操作提前到编译期性能还会好一点

好了,说完上面的思路原理,我们再来看Kotlin该如何使用这种方法呢?

inline关键字

Kotlin中可以使用inline将inline修饰的方法复制到调用方。被inline修饰的方法也叫作内联函数。

使用场景:集合中的中间操作符都会使用inline,当然也可以指定不内联的参数方法,使用noinline修饰这个方法参数。

内联特点

非局部返回

非局部返回:顾名思义全局针对的不是当前方法体

return只作用于当前的函数体。

1.如果lambda中写return编译会报错,lambda中不允许写return关键字。但是可以通过给调用的方法加入inline关键字,将方法复制到调用方这样就可以return了因为他就是很正常的返回,但是结果会变得不一样,因为处于同一个方法体return之后的语句不会执行,这也叫做非局部返回。这种方式在集合遍历中非常有用。由于集合api都是inline的函数所以return后直接返回不在遍历之后元素

2.第二种方式也就是使用@,@方法名。可以指定returh作用的方法体

具体化参数类型refried

参数类型:可以猜到对应的就是泛型。那么具体化又是什么意思呢?

java和kotlin一样都是在运行时类型擦除的所有我们无法获取到泛型的具体类型

eg:我们只能获取到List< E >,而无法获取到List< String >

但是上面说到inline关键字是将inline方法体复制到调用方的方法体中,所以其传入的参数我们是可以知道具体类型的。

在inline修饰的方法中使用refried关键字修饰泛型去打印这个泛型的class发现确实可以获取到具体类型。

inline的缺点

我们了解了它实现的原理就是复制方法体到调用的地方,那么缺点也可想而知:

  • inline修饰的方法体过多,导致调用方的方法体庞大
  • 内联函数无法获得闭包类的私有成员,除非声明为internal

总结

没有觉得的好与坏,了解了实现原理之后再决定使用哪种技术方案符合自己的需求。


目录
相关文章
|
9月前
|
安全 Java 编译器
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
Kotlin 作为 Android 开发的首选语言,其基础语法和特性需要重点学习。本文概括总结了 Kotlin 的基本类型、关键字、函数、闭包、高阶函数、类与对象等核心知识点,并给出示例代码进行讲解。
154 0
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
|
9月前
|
Java Kotlin
Kotlin中匿名函数(又称为Lambda,或者闭包)和高阶函数的详解
Kotlin中匿名函数(又称为Lambda,或者闭包)和高阶函数的详解
81 0
|
12月前
|
安全 IDE JavaScript
From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
Kotlin 是什么? 可以做什么? Android 官方开发语言从Java变为Kotlin,Java 有哪些问题? Kotlin的优点 Kotlin 特性(Features)
11543 1
From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了
|
Java 开发者 Kotlin
Kotlin中lambda表达式详解
lambda运算时java后面版本引进的,所以实现的仅仅是从形式上简化代码,内部的优化并不是非常出色,而Kotlin一开始就支持函数式编程,使得其lambda表达式具有性能上的优势,同时Kotlin简洁的风格也给lambda表达式进一步简化提供了一个良好的实现方式,下面带大家具体看看他们之间的区别以及如何更好的使用Kotlin的极简化lambda表达式
134 0
Kotlin中lambda表达式详解
|
算法 Java 编译器
Kotlin学历之函数与Lambda表达式
Kotlin学历之函数与Lambda表达式
80 0
|
Java Kotlin
【Kotlin】Lambda 表达式 ( 简介 | 表达式语法 | 表达式类型 | 表达式返回值 | 调用方式 | 完整示例 )
【Kotlin】Lambda 表达式 ( 简介 | 表达式语法 | 表达式类型 | 表达式返回值 | 调用方式 | 完整示例 )
259 0
【Kotlin】Lambda 表达式 ( 简介 | 表达式语法 | 表达式类型 | 表达式返回值 | 调用方式 | 完整示例 )
Kotlin的Lambda表达式
一、什么是Lambda表达式 就是匿名函数 写法:{[参数列表] -> [函数体,最后一行是返回值]} **举例:**val sum = {a: Int, b: Int -> a+b} 二、Lambda 的类型 ()-...
1333 0
|
17小时前
|
移动开发 API Android开发
构建高效Android应用:Kotlin协程的实践指南
【5月更文挑战第11天】 在移动开发领域,性能优化和资源管理是至关重要的。特别地,对于Android开发者来说,合理利用Kotlin协程可以极大地改善应用的响应性和稳定性。本文将深入探讨Kotlin协程在Android中的实际应用,包括它们如何简化异步编程模型、提高UI线程的响应性,以及减少内存消耗。我们将通过具体案例分析,了解如何在实际项目中有效地使用协程,从而帮助开发者构建更加高效的Android应用程序。
|
17小时前
|
移动开发 数据处理 Android开发
构建高效Android应用:Kotlin协程的实践与优化策略
【5月更文挑战第14天】在移动开发领域,性能优化和资源管理是提升用户体验的关键因素之一。随着Kotlin语言的普及,其异步编程解决方案——协程,已经成为Android开发者手中的强大工具。本文将深入探讨Kotlin协程在Android应用中的实践方法,分析其在处理异步任务时带来的优势,并提出一系列优化策略,帮助开发者构建更加高效、响应迅速的Android应用。通过具体案例分析和性能对比,我们将展示如何充分利用协程来简化代码结构,提高应用性能,并确保用户界面的流畅性。