Kotlin与java8的SAM转换对比(进阶)
作者:DK_BurNIng 发布时间:2023-05-15 11:50:35
什么是sam 转换
Single Abstract Method 实际上这是java8中提出的概念,你就把他理解为是 一个方法的接口 的就可以了
看一下我们每天都在使用的线程池
ExecutorService executorService= Executors.newScheduledThreadPool(3);
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
});
用下面的java8中的lambda 来写 也是可以的。
xecutorService.execute(()->System.out.println("hello world"));
所以说 这两种写法是 等价 的。 但是这里要强调的是 java中的lambda是没有类型的,所以他必须需要一个接口来接受他。
kotlin中的sam
val executorService: ExecutorService = Executors.newScheduledThreadPool(3)
//kotlin中的 匿名内部类的标准写法
executorService.submit(object :Runnable{
override fun run() {
System.out.println("hello world")
}
})
kotlin中的lambda 这里可以这么写
executorService.submit { System.out.println("hello world") }
这里要注意的是 java的lambda是没有类型的,但是kotlin的lambda有类型 。
上文中的例子 这个kotlin的lambda的类型就是 ()->Unit 是一个没有参数也没有返回值的类型
对于kotlin中的lambda来说,仔细看上面的图 就可以知道。
这里实际上是创建了一个runnable 并且在这个runnable里面 包装了一下lambda,并不是直接转换的 。
//kotlin中 匿名内部类 还可以这么写
executorService.submit(Runnable { println("hello world") })
上面的代码 我们再解释一下 ,kotlin的编译器 再遇到上面的代码的时候 实际上 是 帮我们生成了 一个函数
这个函数的作用就是接收一个 lambda表达式 然后帮我们生成对应的代码
kotlin中sam 转换的坑
java中的lambda是假的,只是一个sam而已。 kotlin的lambda是真的,只不过他还支持sam。是支持sam转换的。
下面定义一个kotlin的接口 以及kotlin的方法
interface Invokable{
fun invoke()
}
fun submit(invokable: Invokable){
invokable.invoke()
}
然后我们看看调用:
看看报错的原因
Type mismatch: inferred type is () -> Unit but Invokable was expected
提示我们 这里 是需要一个invokable,但是给了一个lambda ,不符合要求,所以编译不能通过。
这个可以理解吧,前面已经讲过了。
fun submit2(block:()->Unit){
block.invoke()
}
如果我们定义一个这样的函数 那显然就是可以的了。就可以直接使用lambda了。
当然如果每次这么写,函数参数也比较难写,所以我们干脆 就起个别名
typealias Funtionx = () -> Unit
fun submit2(block: Funtionx) {
block.invoke()
}
另外就是在kotlin中使用sam转换的时候 一定要小心remove的写法,例如:
我们定义一个简单的event类:
public class EventManager {
interface OnEventListener {
void onEvent(int event);
}
private List<OnEventListener> onEventListeners=new ArrayList<OnEventListener>();
public void addOnEventListener(OnEventListener listener){
onEventListeners.add(listener);
}
public void removeEventListener(OnEventListener listener){
onEventListeners.remove(listener);
}
}
现在 kotlin代码 我们要add 一个监听
val eventManager = EventManager()
eventManager.addOnEventListener {
println("onEvent$it")
}
lambda写起来很方便,但是你要小心了,你这么写的话 你是没办法remove的。 你仔细想一想,上面的写法 等于是
eventManager.addOnEventListener(object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
{
println("onEvent$event")
}()
}
})
也等于是
eventManager.addOnEventListener(object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
println("onEvent$event")
}
})
这个创建匿名对象的过程 被编译器做了,你是接触不到这个object的。
所以自然也就没办法去remove了。
遇到这种需要remove的情况 我们就可以用如下写法:
val onEvent = EventManager.OnEventListener {
println("onEvent$it")
}
eventManager.addOnEventListener(onEvent)
eventManager.removeEventListener(onEvent)
或者
val onEvent2 = object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
println("onEvent$event")
}
}
这种写法虽然丑是丑了一点,但是言简意赅,不会出歧义 也不会出错。
来源:https://juejin.im/post/5eabe9e3e51d454dea6fd26c
猜你喜欢
- 前言当初年少懵懂,那年夏天填志愿选专业,父母听其他长辈说选择计算机专业好。从那以后,我的身上就有了计院深深的烙印。从寝室到机房,从机房到图书
- @Validated和BindingResult 使用遇到的坑@Validated 与BindingResult 需要相邻,否则 变量res
- Spring的最基本的能力就是DI,即依赖注入,或控制反转,它可以为Bean注入其依赖的其他Bean。一个Bean依赖其他Bean一般是通过
- 这篇文章主要介绍了java内存泄漏与内存溢出关系解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友
- SpringCloudStream配置以下配置摘自《SpringCloud微服务实战》,配置主要包括两大部分:Stream配置(基础配置、通
- Java的SPI机制实例详解SPI的全名为Service Provider Interface.普通开发人员可能不熟悉,因为这个是针对厂商或
- 有人问我,怎么判断一个点是不是在多边形内,本来想着把这个多边形分成一个又一个三角形,如图, 然后判断这个点是不是在某个三角形中,如
- 前言本节将介绍如何设置和使用MongoDB 驱动程序,通过 java实现与MongoDB服务端的通信功能,用户可以在此基础上进行各种Java
- 前言最近在改进项目的并发功能,但开发起来磕磕碰碰的。看了好多资料,总算加深了认识。于是打算配合查看源代码,总结并发编程的原理。准备从用得最多
- 1. Dubbo是什么?Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,
- @PathVariable和@RequestParam传参为空@RestControllerpublic class UserControl
- 本文实例为大家分享了swing登录注册界面展示的具体代码,供大家参考,具体内容如下开发环境:Eclipse Neon.3 Release (
- 在平时的开发过程中,会有很多场景需要实时监听文件的变化,如下:1、通过实时监控 mysql 的 binlog 日志实现数据同步2、修改配置文
- 软引用简介软引用是用来表示某个引用会被GC(垃圾处理器)收集的类。当有引用指向某个obj的时候,通常发生GC的时候不会把这个对象处理掉,但是
- 今天给大家介绍一下SpringBoot中JPA的一些常用操作,例如:增删改查、分页、排序、事务操作等功能。下面先来介绍一下JPA中一些常用的
- 一、项目简述功能包括: 前台实现:用户浏览菜单、菜品分类筛选、查看菜单详 情、添加购物车、购物车结算、会员券、个人订单查询等 等。 后台实现
- 一、重载 1、重载示意 重载(Overload)是重新加载的意思,指的是同一个类中同名,但是参
- 这篇文章主要介绍了Java方法参数传递机制原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可
- 上篇文章中我们介绍了浅谈Spring的两种配置容器,接下来我们就了解下spring中的FactoryBean的相关内容,具体如下。从Sess
- 就我们所知道的,java中有子类和父类,子类由于继承父类而形成,那么父类还有没有父类呢?答案是有了,父类的父类就是object类,一切父类都