Kotlin与java8的SAM转换对比
2020-06-03 16:06:45来源:博客园 阅读 ()
Kotlin与java8的SAM转换对比
什么是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 来写 也是可以的。
executorService.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") } }
这种写法虽然丑是丑了一点,但是言简意赅,不会出歧义 也不会出错。
“大清亡于闭关锁国,学习技术需要交流和资料”。 在这里我给大家准备了很多的学习资料免费获取,包括但不限于java进阶学习资料、技术干货、大厂面试题系列、技术动向、职业生涯等一切有关程序员的分享.
java进阶方法笔记,学习资料,面试题,电子书籍免费领取,让你成为java大神,追到自己的女神,走向人生巅峰
原文链接:https://www.cnblogs.com/coderjava/p/13038860.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- java8 stream的分组功能,具体时候是真的好用 2020-06-10
- JAVA8 Stream流 2020-06-02
- Spring boot Sample 003之spring-boot-configuration-proper 2020-06-01
- JAVA8 Lambda表达式 2020-05-31
- java8 新特性Stream流的应用 2020-05-16
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash