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与java8的SAM转换对比(进阶)

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

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


//kotlin中 匿名内部类 还可以这么写
executorService.submit(Runnable { println("hello world") })

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

Kotlin与java8的SAM转换对比(进阶)

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

kotlin中sam 转换的坑

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

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


interface Invokable{
fun invoke()
}

fun submit(invokable: Invokable){
invokable.invoke()
}

然后我们看看调用:

Kotlin与java8的SAM转换对比(进阶)

看看报错的原因

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

标签:Kotlin,java8,SAM
0
投稿

猜你喜欢

  • 使用Postman传递arraylist数据给springboot方式

    2022-08-27 01:13:01
  • WPF仿LiveCharts实现饼图的绘制

    2022-02-08 02:17:05
  • iOS中的导航栏UINavigationBar与工具栏UIToolBar要点解析

    2023-07-08 16:52:22
  • volatile与happens-before的关系与内存一致性错误

    2021-12-13 20:25:37
  • Kotlin协程的线程调度示例详解

    2023-12-26 20:19:56
  • 在Android模拟器上模拟GPS功能总是null的解决方法

    2023-09-16 16:51:15
  • Eclipse+Java+Swing实现学生成绩管理系统的实例代码

    2022-12-14 15:35:04
  • Android复选框CheckBox与开关按钮Switch及单选按钮RadioButton使用示例详解

    2023-02-06 18:20:42
  • android端使用openCV实现车牌检测

    2023-02-26 07:50:50
  • Spring Boot 利用 XML 方式整合 MyBatis

    2023-02-09 23:01:18
  • 使用spring框架中的组件发送邮件功能说明

    2022-12-29 03:53:55
  • C语言关于时间复杂度详解

    2022-08-14 02:33:04
  • 学会使用C#异常

    2021-08-17 23:31:19
  • C#中4种深拷贝方法介绍

    2023-01-02 21:16:11
  • Java人民币小写转大写字符串的实现

    2021-10-24 00:52:34
  • c#与js随机数生成方法

    2023-12-14 12:30:36
  • idea2020.3.3集成maven及遇到的坑(推荐)

    2021-11-18 04:18:54
  • Java操作pdf的工具类itext的处理方法

    2023-07-14 11:51:53
  • Spring Cache简单介绍和使用大全

    2023-11-25 04:46:46
  • C#如何绑定多个按钮到同一个事件

    2022-09-09 16:20:12
  • asp之家 软件编程 m.aspxhome.com