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

 更新时间:2020年05月02日 09:23:28   作者:DK_BurNIng  
这篇文章主要介绍了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 来写 也是可以的。

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

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

到此这篇关于Kotlin与java8的SAM转换对比的文章就介绍到这了,更多相关Kotlin与java8的SAM转换 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java Socket编程简介_动力节点Java学院整理

    Java Socket编程简介_动力节点Java学院整理

    这篇文章主要介绍了Java Socket编程简介的相关知识,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-05-05
  • Java常用排序算法及性能测试集合

    Java常用排序算法及性能测试集合

    周末天气不好,在家无事,把常用排序算法理了一遍,收获不小,特写文章纪念。这些算法在学校的时候学过一遍,很多原理都忘记了
    2013-06-06
  • Spring解决循环依赖的方法(三级缓存)

    Spring解决循环依赖的方法(三级缓存)

    今天,我们要说的是spring是如何解决循环依赖的。对于一个问题说解决之前,我们首先要先明确形成问题的本因。那么循环依赖,何为循环依赖呢?感兴趣的朋友跟随小编一起看看吧
    2021-11-11
  • SparkSQL使用快速入门

    SparkSQL使用快速入门

    spark SQL是spark的一个模块,主要用于进行结构化数据的处理。它提供的最核心的编程抽象就是DataFrame。这篇文章主要介绍了SparkSQL使用快速入门,需要的朋友可以参考下
    2021-08-08
  • Spring Boot 如何生成微信小程序短连接及发送短信在短信中打开小程序操作

    Spring Boot 如何生成微信小程序短连接及发送短信在短信中打开小程序操作

    最近遇到这样的需求需要发送短信,通过短信中的短连接打开小程序操作,下面小编给大家分享Spring Boot 如何生成微信小程序短连接发送短信在短信中打开小程序操作,感兴趣的朋友跟随小编一起看看吧
    2024-03-03
  • Spring cloud 实现房源查询功能的实例代码

    Spring cloud 实现房源查询功能的实例代码

    这篇文章主要介绍了Spring cloud 实现房源查询功能,本项目是一个多模块项目,创建一个 Spring Initializr 项目 不自动添加依赖项,完成创建后删除自带的src目录,并在根目录下创建新的maven模块,需要的朋友可以参考下
    2022-09-09
  • java并发请求下数据插入重复问题的解决方法

    java并发请求下数据插入重复问题的解决方法

    现在遇到一个项目,移动设备存储数据,然后一起上传,那就出现了许多重复数据,这篇文章主要给大家介绍了关于java并发请求下数据插入重复问题的解决方法,需要的朋友可以参考下
    2021-11-11
  • Java循环嵌套详解及经典列题

    Java循环嵌套详解及经典列题

    这篇文章主要给大家介绍了关于Java循环嵌套详解及经典列题,包括循环嵌套的结构、变量作用域、不同类型循环的嵌套等,通过示例和经典练习题,展示了如何使用循环嵌套解决实际问题,需要的朋友可以参考下
    2024-12-12
  • maven打包zip包含bin下启动脚本的完整代码

    maven打包zip包含bin下启动脚本的完整代码

    这篇文章主要介绍了maven打包zip包含bin下启动脚本,本文给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • SpringBoot Redis用注释实现接口限流详解

    SpringBoot Redis用注释实现接口限流详解

    Redis 除了做缓存,还能干很多很多事情:分布式锁、限流、处理请求接口幂等性。。。太多太多了~今天想和小伙伴们聊聊用 Redis 处理接口限流,这也是最近的 项目涉及到这个知识点了,我就拎出来和大家聊聊这个话题
    2022-07-07

最新评论