Kotlin中的sam(函数式接口)详解

用lambda表达式去表示java中的匿名类实例

在使用java去给一个按钮设置监听我们通常会通过创建匿名类实例,如下

Button.setOnClickListener(new OnClickListener()){
  @Override
  public void onClick(View v){
    Toast.makeText(this,"Hello World",Toast.LENGTH_LONG).show()
  }
}

在kotlin我们可以通过传递一个lambda表达式去代替这个实例

btn_test.setOnClickListener { view : View ->
      Toast.makeText(this,"Hello World",Toast.LENGTH_LONG).show()
}

可以以这种方式去实现的原因是OnClickListener接口只有一个抽象方法,这种接口在kotlin中被当作函数式接口,或者SAM接口,SAM代表单抽象方法,类似的还有像Runnable和Callable这样的函数式接口.

把lambda当作参数传递给Java方法

我们在java中定义一个

void postponeComputation(int delay,Runnable computation){
}

然后使用lambda表达式去传递Runnable这个参数

postponeComputation(1000){
    print("hello world")
}

注意这个lambda实参编译器会自动把它转换成一个Runnable实例. 这种调用方式效果和显示的实现一个Runnable匿名对象一样

postponeComputation(1000,object : Runnable{
    override fun run(){
        println(42)
    }
})

但实际不一样的是,每次调用这种语句会重复创建Runnable对象,而使用lambda表达式作为实参如果没有访问任何来自定义它的函数变量那么只会创建一个对象.

如果想要完全等价需要这样去定义

val runnable = Runaable{ println(42) }
fun handleComputation(){
   postponeComputation(1000,runnable)
}

另外如果从包围它的作用域中捕捉了变量,每次调用就不会重用同一个实例了, 如下调用每次都会使用一个新的Runnable实例.

fun handleComputation(id : String){
   postponeComputation(1000){println(id)}
}

实际上从kotlin1.0起, 每个lambda都会被编译成一个匿名类,如果lambda捕捉了变量,每个被捕捉的变量会在匿名类中有对应的字段.

SAM构造方法:显式地把lambda转换成函数式接口.

在有的方法中需要返回一个函数式接口,不能返回一个lambda, 可以用SAM构造方法把它包装起来. 如下

fun createAllDoneRunable() : Runnable{
  return Runnable{ println(“All done”) }
}

SAM函数名称和底层函数式接口的名称一样. SAM构造方法只接收一个参数-一个被用作函数式接口单抽象方法体的lambda,并返回一个接口类的实例.

另外除了返回值通过lambda创建函数式接口外,也可以把lambda生成的函数式接口放在一个变量中,如下

val listener = OnClickListener{
  view -> val text = when(view.id){
    R.id.button1 -> “First button”
    R.id.button2 -> “Second button”
    else -> “Unknown button"
  }
  toast(text)
}
button1.setOnClickListener(listener)
button2.setOnClickListener(listener)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Kotlin整合Vertx开发Web应用

    今天我们尝试Kotlin整合Vertx,并决定建立一个非常简单的Web应用程序,使用Kotlin和Vertx作为编程语言进行编码构建. 生成项目 打开控制台窗口执行以下代码进行生成一个maven项目 复制代码 代码如下: mvn archetype:generate -DgroupId=com.edurt.kvi -DartifactId=kotlin-vertx-integration -DarchetypeArtifactId=maven-archetype-quickstart -Dver

  • Kotlin 接口与 Java8 新特性接口详解

    前言 在看一本关于高性能编程的时候发现 Java8 中关于接口的新特性的介绍,这个特性是真的棒,解决了一个接口中有多个方法,但并不想实现该接口的类都去实现所有的方法,简单的说就是在类需要的情况再去重写接口.所以有了以下的特性出现. 接口增强 在 Java8 的中接口特性中增加以下俩种特性: 在接口中可以使用 default 关键字修饰默认方法或扩展方法,抽象方法因为其特性的原因无法使用 接口可以使用 static 声明为静态方法,可以通过类直接调用Android Studio 中使用 Java8

  • SpringBoot整合Kotlin构建Web服务的方法示例

    今天我们尝试Spring Boot整合Kotlin,并决定建立一个非常简单的Spring Boot微服务,使用Kotlin作为编程语言进行编码构建. 创建一个简单的Spring Boot应用程序.我会在这里使用maven构建项目: <?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  • Kotlin函数默认值的完全讲解

    函数默认值 周所周知,Java语言并不支持参数使用默认值.有人说这是因为"默认参数"和"方法重载"同时支持的话有二义性的问题,具体真正的原因我不得而知.但是对我个人来说,Java不支持这个特性的确挺让我蛋疼的,虽然说使用方法重载也可以间接实现与默认参数这个特性相同的功能,但这就意味着你得写更多的代码-- 简要介绍 Kotlin函数定义时,支持对参数指定默认值,这样就有效减少Java之前定义重载函数的数量. 简要对比如下: 1.Java函数定义,如果sayHelloT

  • 小谈Kotlin的空处理的使用

    近来关于 Kotlin 的文章着实不少,Google 官方的支持让越来越多的开发者开始关注 Kotlin.不久前加入的项目用的是 Kotlin 与 Java 混合开发的模式,纸上得来终觉浅,终于可以实践一把新语言. 本文就来小谈一下 Kotlin 中的空处理. 一.上手的确容易 先扯一扯 Kotlin 学习本身. 之前各种听人说上手容易,但真要切换到另一门语言,难免还是会踌躇是否有这个必要.现在因为工作关系直接上手 Kotlin,感受是 真香(上手的确容易) . 首先在代码阅读层面,对于有 Ja

  • Kotlin中的sam(函数式接口)详解

    用lambda表达式去表示java中的匿名类实例 在使用java去给一个按钮设置监听我们通常会通过创建匿名类实例,如下 Button.setOnClickListener(new OnClickListener()){ @Override public void onClick(View v){ Toast.makeText(this,"Hello World",Toast.LENGTH_LONG).show() } } 在kotlin我们可以通过传递一个lambda表达式去代替这个实

  • JAVALambda表达式与函数式接口详解

    Lambda表达式的诞生是为了解决JAVA创建匿名内部类代码冗余的问题.例子如下: public class Lambda { public static void main(String[] args) { Gog gog = new Gog() { @Override public void say() { System.out.println("WOW"); } }; gog.say(); } } interface Gog { void say(); } 这里我们想实现接口的s

  • Kotlin中日志的使用方法详解

    1 引言 想必学过Java的人都知道一个@Slf4j使用得多么的舒服: @Slf4j public class TestController{ @GetMapping("/test") public String test(){ log.debug("debug"); return "test"; } } 但是很不幸在Kotlin中并没有这种注解,因此,本文给出了一种类似@Slf4j注解在Kotlin中的使用方法,以及介绍一个100%使用Kotl

  • Kotlin 语言中调用 JavaScript 方法实例详解

    Kotlin 语言中调用 JavaScript 方法实例详解 Kotlin 已被设计为能够与 Java 平台轻松互操作.它将 Java 类视为 Kotlin 类,并且 Java 也将 Kotlin 类视为 Java 类.但是,JavaScript 是一种动态类型语言,这意味着它不会在编译期检查类型.你可以通过动态类型在 Kotlin 中自由地与 JavaScript 交流,但是如果你想要 Kotlin 类型系统的全部威力 ,你可以为 JavaScript 库创建 Kotlin 头文件. 内联 J

  • JavaScript中的函数式编程详解

    函数式编程 函数式编程是一种编程范式,是一种构建计算机程序结构和元素的风格,它把计算看作是对数学函数的评估,避免了状态的变化和数据的可变,与函数式编程相对的是命令式编程.我们有这样一个需求,给数组的每个数字加一: // 数组每个数字加一, 命令式编程 let arr = [1, 2, 3, 4]; let newArr = []; for(let i = 0; i < arr.length; i++){ newArr.push(arr[i] + 1); } console.log(newArr)

  • Java中Lambda表达式的使用详解

    目录 理解函数式接口以及 Lambda表达式的发展过程 Lambda表达式及语法 一起来看看具体的使用 你需要注意什么 Lambda的实际运用 1.对集合排序 2.遍历集合 3.遍历集合(带条件) 4.代替 Runnable,开启一个线程 理解函数式接口以及 Lambda表达式的发展过程 任何接口,只包含唯一一个抽象方法,就是函数式接口 /** * lambdab表达式的发展 */ public class TestLambda1 { //3.静态内部类 static class Like2 i

  • Kotlin协程Dispatchers原理示例详解

    目录 前置知识 demo startCoroutineCancellable intercepted()函数 DefaultScheduler中找dispatch函数 Runnable传入 Worker线程执行逻辑 小结 前置知识 Kotlin协程不是什么空中阁楼,Kotlin源代码会被编译成class字节码文件,最终会运行到虚拟机中.所以从本质上讲,Kotlin和Java是类似的,都是可以编译产生class的语言,但最终还是会受到虚拟机的限制,它们的代码最终会在虚拟机上的某个线程上被执行. 之

  • Java中注解与原理分析详解

    目录 一.注解基础 二.注解原理 三.常用注解 1.JDK注解 2.Lombok注解 四.自定义注解 1.同步控制 2.类型引擎 一.注解基础 注解即标注与解析,在Java的代码工程中,注解的使用几乎是无处不在,甚至多到被忽视: 无论是在JDK源码或者框架组件,都在使用注解能力完成各种识别和解析动作:在对系统功能封装时,也会依赖注解能力简化各种逻辑的重复实现: 基础接口 在Annotation的源码注释中有说明:所有的注解类型都需要继承该公共接口,本质上看注解是接口,但是代码并没有显式声明继承关

  • Android开发之Kotlin委托的原理与使用详解

    目录 前言 一.接口/类委托 二.属性委托 三.延迟委托 四.观察者委托 五.Map委托 总结 前言 在设计模式中,委托模式(Delegate Pattern)与代理模式都是我们常用的设计模式(Proxy Pattern),两者非常的相似,又有细小的区分. 委托模式中,委托对象和被委托对象都是同一类型的对象,委托对象将任务委托给被委托对象来完成.委托模式可以用于实现事件监听器.回调函数等功能. 代理模式中,代理对象与被代理对象是两种不同的对象,代理对象代表被代理对象的功能,代理对象可以控制客户对

  • python中模块的__all__属性详解

    python模块中的__all__属性,可用于模块导入时限制,如: from module import * 此时被导入模块若定义了__all__属性,则只有__all__内指定的属性.方法.类可被导入. 若没定义,则导入模块内的所有公有属性,方法和类 # kk.py class A(): def __init__(self,name,age): self.name=name self.age=age class B(): def __init__(self,name,id): self.nam

随机推荐