Lambda 表达式

简介

Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。

1.Java 8 的 Lambda

在 Java 8 之前我们使用 Thread 可能是这样的:

   new Thread(new Runnable() {    
        public void run() {        
              System.out.println("test");    
       }
   }).start();

在 Java 8 之后开始支持 Lambda 表达式,于是我们可以这样写:

   new Thread(()->System.out.println("test")).start();

从 Runnable 的源码可以发现,它使用了 @FunctionalInterface,@FunctionalInterface 是 Java 8 为函数式接口引入的一个新的注解。表明该接口是函数式接口,只包含唯一一个抽象方法。任何可以接受一个函数式接口实例的地方,都可以用 Lambda 表达式。

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

Java 8 的 Lambda 表达式是一个 SAM(Single Abstract Method) 类型。因为 Java 没有像 Kotlin 那样拥有函数类型,所以需要借助 SAM 类型来实现 Lambda 表达式。

Java 8 的 Lambda 语法:

(参数列表) -> {函数体}

对于无参的 Lambda 表达式:

() -> {函数体}

对于单个参数的 Lambda 表达式:

(x) -> {函数体}

它可以简化为:

x -> {函数体}

对于多个参数的 Lambda 表达式:

(x,y,z) -> {函数体}

如果函数体只有一行代码,则可以省略函数体的大括号。另外对于参数列表,由于 Java 的编译器可以进行类型推断,所以不需要声明参数的类型。

在 Java 8 中,Lambda 的创建是通过字节码指令invokedynamic来完成的,减少了类型和实例的创建消耗。在 Java 8 之前,我们使用匿名类,但是匿名类需要创建新的对象。

2.Kotlin 的 Lambda 语法

Kotlin 的 Lambda 表达式使用一对大括号括起来,后面依次跟着各个参数及其类型,紧接着是" -> ",函数体定义在" -> "之后。函数体的最后一句的表达式结果就是 Lambda 表达式的返回值。如果 Lambda 表达式没有参数的话,可以省略" -> "。

Kotlin 的 Lambda 语法:

 {
     参数列表 -> 函数体
 }

使用 Kotlin 来实现上述代码:

   Thread { println("test") }.start()

看上去,Kotlin 的 Lambda 语法相比 Java 的 Lambda 语法似乎更加简洁。

3.简化 Kotlin 的 Lambda 表达式

Kotlin 的 Lambda 表达式可以不断地被简化。以处理 Android View 的点击事件为例,使用 Java 的代码大致如下:

view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ...
    }
});

按照 Java 的风格来编写 Kotlin 的代码,使用 Kotlin 的对象表达式:

view.setOnClickListener(object :View.OnClickListener{
    override fun onClick(v: View?) { 
        ...
    }
})

再对上述代码使用 Lambda 表达式:

view.setOnClickListener({ v ->   
    ...
})

如果参数为函数类型并且是最后一个参数,那么可以将参数移到函数的括号外面:

view.setOnClickListener() { v ->  
    ...
}

如果参数只有一个 Lambda 表达式,那么函数的小括号可以省略:

view.setOnClickListener { v ->
    ...
}

最后,在点击事件里如果会使用到 view,那么" v -> "可以省略,使用默认参数it进行替代:

view.setOnClickListener {
    it.visibility = View.GONE
    ...
}

4.总结

小结一下简化 Lambda 表达式的规则:

  • 在函数中,最后一个参数是函数类型,那么可以将 Lambda 可以移到函数的括号外面。
  • 如果函数的参数只有一个 Lambda ,那么函数的小括号可省略。
  • 在 Lambda 表达式中只有一个参数,可以使用默认参数 it 进行替代。
  • 对于有多个参数的 Lambda 表达式,如果某个参数未使用,可以用下划线("_")取代其名称
  • 入参、返回值与形参一致的函数,可以用方法引用的方式作为实参传入。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值