kotlin 开发 java8_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 是一个没有参数也没有返回值的类型

819c1a3538a38412b5478b44a285c05e.png

对于kotlin中的lambda来说,仔细看上面的图 就可以知道。

这里实际上是创建了一个runnable 并且在这个runnable里面包装了一下lambda,并不是直接转换的。

//kotlin中 匿名内部类 还可以这么写

executorService.submit(Runnable { println("hello world") })

复制代码

上面的代码 我们再解释一下 ,kotlin的编译器 再遇到上面的代码的时候 实际上 是帮我们生成了

一个函数

31c6f3e235d00e5c0769b33d2020e512.png

这个函数的作用就是接收一个 lambda表达式 然后帮我们生成对应的代码

kotlin中sam 转换的坑

java中的lambda是假的,只是一个sam而已。 kotlin的lambda是真的,只不过他还支持sam。是支持sam转换的。

下面定义一个kotlin的接口 以及kotlin的方法

interface Invokable{

fun invoke()

}

fun submit(invokable: Invokable){

invokable.invoke()

}

复制代码

然后我们看看调用:

f85767e705ab20db6507bb6cddd35733.png

看看报错的原因

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 onEventListeners=new ArrayList();

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")

}

}

复制代码

这种写法虽然丑是丑了一点,但是言简意赅,不会出歧义 也不会出错。

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[Kotlin与java8的SAM转换对比(进阶)]http://www.zyiz.net/tech/detail-132298.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值