Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
Java中Lambda表达式其实就是创建实例对象的另一种方式,但是它比较特殊,比较简洁,并且创建的是一个匿名对象(万物皆对象!)。
从下边示例代码可以看出,Lambda表达式只是对抽象方法进行了重写,具体的输入是由最终的调用者决定的。只要输入相同,输出就一定相同。
函数式接口:
@FunctionInterface //声明该接口为函数式接口
public interface FunctionInterfaceTest{...void method(T t); // 只能有一个抽象方法
}
Lambda表达式:
// 左边是接口,右边是对抽象方法的重写
FunctionInterfaceTest m = (t)-> System.out.println(t);// 调用
m.method(11); //输出11
Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,即Java不但可以支持OOP还可以支持OOF(面向函数编程)
面向对象思想:
函数式编程思想:
在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口。
简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。
接口<泛型> 引用 = (形参列表) -> { 方法体 }
调用:引用.抽象方法(实参);
,这里调用的是被重写的抽象方法。
因为Lambda表达式是对抽象方法的重写,因而一定要要先了解被重写的抽象方法是如何定义的。
@Test
public void test1(){//未使用Lambda表达式Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("我爱北京天安门");}};r1.run();System.out.println("***********************");//使用Lambda表达式Runnable r2 = () -> {System.out.println("我爱北京故宫");};r2.run();
}
@Test
public void test2(){//未使用Lambda表达式Consumer con = new Consumer() {@Overridepublic void accept(String s) {System.out.println(s);}};con.accept("谎言和誓言的区别是什么?");System.out.println("*******************");//使用Lambda表达式Consumer con1 = (String s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");}
Lambda 表达式中的参数类型都是由编译器推断得出的。Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”。
@Test
public void test3(){//语法格式三使用前Consumer con1 = (String s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*******************");//语法格式三使用后,形参类型可由接口泛型 推断出来Consumer con2 = (s) -> {System.out.println(s);};con2.accept("一个是听得人当真了,一个是说的人当真了");}
@Test
public void test4(){//语法格式四使用前Consumer con1 = (s) -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*******************");//语法格式四使用后Consumer con2 = s -> {System.out.println(s);};con2.accept("一个是听得人当真了,一个是说的人当真了");}
@Test
public void test5(){//语法格式五使用前Comparator com1 = new Comparator() {@Overridepublic int compare(Integer o1, Integer o2) {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);}};System.out.println(com1.compare(12,21));System.out.println("*****************************");//语法格式五使用后Comparator com2 = (o1,o2) -> {System.out.println(o1);System.out.println(o2);return o1.compareTo(o2);};System.out.println(com2.compare(12,6));}
@Test
public void test6(){//语法格式六使用前Comparator com1 = (o1,o2) -> {return o1.compareTo(o2);};System.out.println(com1.compare(12,6));System.out.println("*****************************");//语法格式六使用后Comparator com2 = (o1,o2) -> o1.compareTo(o2);System.out.println(com2.compare(12,21));}@Test
public void test7(){//语法格式六使用前Consumer con1 = s -> {System.out.println(s);};con1.accept("一个是听得人当真了,一个是说的人当真了");System.out.println("*****************************");//语法格式六使用后Consumer con2 = s -> System.out.println(s);con2.accept("一个是听得人当真了,一个是说的人当真了");}
接口功能类型 | 接口 | 抽象方法 | 描述 |
---|---|---|---|
消费型接口 | Consumer | void accept(T t) | 负责逻辑处理,没有返回值 |
供给型接口 | Supplier | T get() | 不需要参数,有返回值 |
函数型接口 | Function | R apply(T t) | 接收一个参数,并返回指定类型数据 |
判断型接口 | Predicate | boolean test(T t) | 接收一个参数,返回布尔值 |