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


猜你喜欢
- 一提到委托,浮现在我们脑海中的大概是听的最多的就是类似C++的函数指针吧,呵呵,至少我的第一个反应是这样的。关于委托的定义和使用,已经有诸多
- 该说不唠,直接上代码。可直接复制使用package com.yuezhi.util;import java.math.BigDecimal;
- 同类型对象的比较三个维度去比较同一性相等性相似性样例引入想象一下这样的一个场景:小王去图书馆借了一本java核心技术卷1,如图不幸的是小王把
- 摘要分析验证码素材图片混淆原理,并采用selenium模拟人拖动滑块过程,进而破解验证码。人工验证的过程1、打开威锋网注册页面2、移动鼠标至
- 在上一节,我们已经完成了项目的整体技术架构设计和具体的数据库设计,接下来,我们搭建整体的开发框架。开发工具选用Idea。开发工具只是为了提高
- 本文实例为大家分享了Java使用MulticastSocket实现群聊应用程序的具体代码,供大家参考,具体内容如下在这篇文章中,讨论了一个使
- 题外话:学习.NET已经有一年了,从C#->ASP.NET->WPF。主要以看电子书为主,比较少写代码。现在回头学习以前接触过的
- 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助在AndroidManifest.xml注册ACTION事件<activi
- 目前越来越多的app在注册或是进行对应操作时,要求获取短信验证码,在点击了获取短信验证码的按钮后,就是出现倒计时,比如倒计时120S,在倒计
- 本文实例讲述了Java实现的质因数分解操作。分享给大家供大家参考,具体如下:这里演示java通过递归实现质因数分解,代码如下:import
- 你要学会:流的概念处理字节流的类处理字符流的类Java标准输入输出文件管理类Java语言的输入输出类库1.流的概念流是指计算机各部件之间的数
- 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明。一、相关约定为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定
- 前言上一篇文章已经介绍了fluent-mybatis项目的构建,文章地址:Java Fluent Mybatis实战之构建项目与代码生成篇上
- 废话不多说了,下面代码给大家介绍下利用正则表达式判断字符的方法,具体代码如下所示:using System;using System.Tex
- PipedOutputStream和PipedInputStream在java中,PipedOutputStream和PipedInputS
- List 的方法列表方法名功能说明ArrayList()构造方法,用于创建一个空的数组列表add(E e)将指定的元素添加到此列表的尾部ge
- 如果出现:org.apache.ibatis.binding.BindingException: Invalid bound stateme
- MongoDB是介于关系数据库和非关系数据库之间的一种产品,文件的存储格式为BSON(一种JSON的扩展),这里就主要介绍Java通过使用m
- 在项目开发中,我们经常需要进行动态添加组件,其中可添加的部分有两项:布局和组件 其中,添加的布局主要有RelativeLayout
- 目录1、什么是LockSupport?2、两类基本API3、LockSupport本质4、LockSupport例子5、LockSuppor