Lambda表达式

Kotlin高阶函数--Higher-Order Function

参数或者返回值为函数类型的函数,在Kotlin中被称为高阶函数。

高阶函数概念源自数学中的高阶函数-在数学中,如果一个函数使用函数作为他的参数或者结果,则他被称为高阶函数。

Java中函数的参数不能是函数

Kotlin中函数可以含有函数类型的参数,且函数的返回值也可以是函数类型

SAM接口--Single Abstract Method

只有一个抽象方法的接口简称SAM接口

函数类型的参数示例

  • 无参数无返回值:(()->Unit)

  • 单Int型参数返回:String(Int->String)

双冒号::method是什么?(函数引用Function Reference)

::method这种写法叫做函数引用;(method在加上::就变成了一个和函数具有相同功能的对象了)

  • 对于一个已经声明好的函数,不管是要把它作为参数传递给函数,还是把它赋值给变量,都需要在函数名的左边加上双冒号

    a(::b)
    val d = ::b
    
  • 在Kotlin中,一个函数名的左边加上双冒号,它就不表示这个函数本身了,而是表示一个对象,或者是一个指向对象的引用,但是这个对象并不是函数本身,而是和函数具有相同功能的对象

    b(1) // 调用函数
    d(1) // 用对象 a 后面加上括号来实现 b() 的等价操作
    (::b)(1) // 用对象 :b 后面加上括号来实现 b() 的等价操作
    
  • 函数类型的对象和普通对象的区别:

    普通类型的对象无法通过对象()这种方法来调用,但是函数类型的对象是可以的,但是这其实是个假的调用,它是Kotlin的语法糖。

    对一个函数类型的对象加括号,加参数,真正调用的是这个对象的invoke()函数

    d(1) // 实际上会调用 d.invoke(1)
    (::b)(1) // 实际上会调用 (::b).invoke(1)
    
    //错误写法,对一个函数调用invoke
    b.invoke(1)
    
  • 双冒号加函数名是一个指向对象的引用,但是并不是指向函数本身。而是指向一个看不见的对象,这个对象复制了原函数的功能,但它并不是原函数

Kotlin中的匿名函数(其实是一个对象,并不是一个函数)

简单来说就是没有名字的函数,本质是一个对象

a(fun(param: Int): String {
    return param.toString()
});
val d = fun(param: Int): String {
    return param.toString()
}
//错误写法,左右两边都有名字,Kotlin是不允许的
val d = fun a(param:Int):String{
    
}

Java中和Kotlin中接口回调设计及使用对比

  • Java

    //定义
    public interface OnClickListener {
      void onClick(View v);
    }
    public void setOnClickListener(OnClickListener listener) {
      this.listener = listener;
    }
    //使用
    view.setOnClickListener(new OnClickListener() {
      @Override
      void onClick(View v) {
        switchToNextPage();
      }
    });
    
  • Kotlin

    //定义
    public interface OnClickListener {
      void onClick(View v);
    }
    fun setOnClickListener(onClick: (View) -> Unit) {
      this.onClick = onClick
    }
    //使用
    view.setOnClickListener(fun(v: View): Unit) {
      switchToNextPage()
    })
    //使用lambda替换
    view.setOnClickListener({ v: View ->
      switchToNextPage()
    })
    

Lambda表达式

  • Lambda表达式示例:

    (parameters) -> expression
    或
    (parameters) ->{ statements; }
    
    // 1. 不需要参数,返回值为 5  
    () -> 5  
    
    // 2. 接收一个参数(数字类型),返回其2倍的值  
    x -> 2 * x  
    
    // 3. 接受2个参数(数字),并返回他们的差值  
    (x, y) -> x – y  
    
    // 4. 接收2个int型整数,返回他们的和  
    (int x, int y) -> x + y  
    
    // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
    (String s) -> System.out.print(s)
    
  • 当Lambda是函数的最后一个参数,或唯一参数,或单参数时的不同写法

    //Lambda是函数的最后一个参数,可以把Lambda写在括号外面
    view.setOnClickListener() { v: View ->
      switchToNextPage()
    }
    //Lambda是函数的唯一参数,直接将()去掉
    view.setOnClickListener { v: View ->
      switchToNextPage()
    }
    //如果Lambda中函数时单参数的,参数也可以省略不写
    view.setOnClickListener {
      switchToNextPage()
    }
    //如果Lambda中函数时多个参数,但是部分参数不需要使用时
    mAdapter.setOnItemClickListener { _, _, position ->
      SocietyHomeAct.toSocietyHome(this, (mAdapter.getItem(position)))
    }
    
  • Kotlin对于省略的唯一参数有默认名字:it

  • Lamda的返回值不是用return返回,而是直接取最后一行代码的值

  • 将匿名函数赋值给变量而不是作为函数参数传递的时候的写法

    val b = fun(param: Int): String {
      return param.toString()
    }
    //简写成Lambda
    val b = { param: Int ->
      return param.toString()
    }
    //错误写法
    val b = {
      return it.toString() // it 报错,因为无法根据上下文推断对象
    }
    //替代方案:给左边的变量指明类型
    val b: (Int) -> String = {
      //错误写法:Lambda的返回值不能用return返回,会直接取最后一行作为返回值
      //return it.toString() // it 可以被推断出是 Int 类型
      it.toString() // it 可以被推断出是 Int 类型
    }
    

Kotlin里的函数和匿名函数以及Lambda表达式的本质

它们都是函数类型的对象

  • 函数:用来实现特定功能的代码块

  • 匿名函数:不是一个函数,是一个具备与函数功能相同的对象

  • Lambda:不是一个函数,是一个函数类型的对象

  • 使用时能怎么使用双冒号加函数名就能怎么使用匿名函数,以及怎么使用Lambda表达式。

Kotlin中的Lambda和Java8的Lambda区别

Java从8开始引入了Lambda支持,主要作用是对于单抽象方法的接口,Java 8允许你用Lambda表达式来创建匿名类对象,但是它本质上还是创建了一个匿名类对象,只不过是一种简化的写法。

Kotlin中的Lambda是实实在在的函数类型的对象,功能更强,写法更多更灵活,

  • Kotlin中的Lambda是函数类型的对象
  • Java 8中的Lambda只是一种便捷的写法,在功能上没有突破

总结

  • 1、在Kotlin中,有一类Java不存在的类型,叫函数类型,这类对象可以当函数来使用的同时,还可以作为函数的参数,函数的返回值,以及赋值给变量

  • 2、创建一个函数类型的对象的三种方式

    ::b//双冒号加函数名
    val b = fun(){}//匿名函数
    val c = {}//Lambda
    
  • 3、双冒号加函数名、匿名函数和Lambda本质都是函数类型的对象;在Kotlin中,匿名函数不是函数,Lambda也只是代码块,Kotlin的Lambda可以归为函数类型的对象。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342