Java 8 -- Lambda表达式(一)

一、定义:

  Lambda表达式是Java 8中最主要的特性之一。那什么是Lambda表达式呢?简单的说,Lambda表达式就是一个匿名函数。有过Javascript或其他函数式编程经验的人来说,应该很熟悉这个概念。但是单纯从Java的角度来看,这个概念还是比较陌生。首先,Java中的函数是不能单独存在的,需要依赖于类,所以函数的执行需要通过类名来调用,即使只有一个方法,也需要定义一个类,JDK中有很多这种接口,例如Runnable接口。其次,JDK 1.8之前,函数只能进行值(对象的引用或基本类型)的传递,而不能传递行为(函数/方法)。所以,要在Java中实现Lambda表达式还是比较困难的(至于怎么实现的,我们后续讨论)。既然这样,那为什么还要引入Lambda表达式呢?主要原因有

  1、简化代码

  2、提高效率

  3、为Java 8中的Stream奠定基础

我们从后续的分析中会很清楚的看到这三个原因。

 

二、Lambda表达式的语法

我们先通过一个最简单的列子来看一下Lambda表达式。

public class LambdaHelloWord {

    public void helloWorld(Runnable runnable){
        runnable.run();
    }

    public static void main(String[] args) {
        LambdaHelloWord lambda = new LambdaHelloWord();
        
        //JDK 1.8之前的实现方式
        lambda.helloWorld(new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello,World!");
            }
        });

        //Lambda表达式实现方式
        lambda.helloWorld(()->System.out.println("Hello,World!"));
    }
}

 这段代码中采用两种方式来打印Hello,World。第一种方式是JDK 1.8之前采用的方式,为了打印Hello,World,需要多行模板代码。而采用Lambda表示则一行代码就可以完成我们想要的功能,没有任何冗余的代码。所以,Lambda表达式确实能够在一定程度上解决Java代码冗长的诟病。

 通过上面的例子,我们仔细分析一下Lambda表达式,Lambda表达式由三部分组成:

  1、参数列表(),因为Runable的run()方法没有参数,所以参数列表为空。
  2、箭头符号->,分割参数列表和函数主题
  3、函数主题System.out.println("Hello,World!"),我们要完成的功能。

 

三、函数接口:

  什么情况下我们可以传递Lambda表达式呢?肯定不可能是所有的函数都能接收Lambda表达式。回到上面的例子,函数helloWorld()接收一个Runnable参数,那Runnable接口的特点是什么----只有一个方法。Java 8 将这种只有一个方法的接口称之为函数式接口,凡是接收函数式接口类型参数的方法,都可以接收Lambda表达式。Java中常见的函数式接口还有Comparator、EventHandler等。除此,Java 8还提供了很多新的函数式编程接口:

  • Predicate 接收T对象并返回boolean
  • Consumer 接收T对象,不返回值
  • Function 接收T对象,返回R对象
  • Supplier 提供T对象,不接收值
  • UnaryOperator 接收T对象,返回T对象
  • BinaryOperator 接收两个T对象,返回T对象

所有的接口在java.util.function包下,除了上面列出的接口,还有很多其他函数接口,不过功能与上面的类似。

根据函数接口的定义,我们很容易实现自己的函数接口(只要定义一个包含一个函数的接口即可):

public interface Operator {
    public int op(int i,int j);
}

这样,我们就可以运用Lambda表达式来使用该接口了:

public class Test {

    public int compute(Operator operator,int i,int j){
        return operator.op(i,j);
    }

    public static void main(String[] args) {
        Test test = new Test();
        //加法操作
        int add = test.compute((i,j)->i+j,10,20);
        System.out.println(add);
        //减法操作
        int subtract = test.compute((i,j)->i-j,10,20);
        System.out.println(subtract);
        //乘法操作
        int multiply = test.compute((i,j)->i*j,10,20);
        System.out.println(multiply);
        //除法操作
        int divide = test.compute((i,j)->{
            if(j==0){
                throw new ArithmeticException();
            }
            return i/j;
        },100,20);
        System.out.println(divide);
    }
}

这样,我们就可以通过一个方法实现了整数的四则运算。值得注意的是,做除法操作时,因为需要对除数做校验,不能直接操作,所以我们将函数体写在一个代码块中。但是请注意,在不使用代码块({})时,我们不需要返回结果,如果采用代码块,则必须有返回值。

 四、总结

  Lambda表达式做为Java 8中的一个非常重要特性,可以非常有效的减少Java 中的模板代码,其本质上是一个匿名函数,并且可以作为函数的参数进行传递,这点与C语言中的函数指针类似。下一篇文章中将从JVM的角度来讨论Lambda表达式是如何实现的。

你可能感兴趣的:(Java 8 -- Lambda表达式(一))