Java的lambda表达式

1. Java的lambda表达式

Java小案例:原始写法

packagecom.aaa.entity;publicclass Program {

public static void main(String[] args) {

Calcal=newCal(){

@Overridepublic int add(int a, int b) {

returna+b;}};System.out.println(cal.add(1,2));}}interface Cal{

int add(int a,int b);}

Java小案例:lambda写法

packagecom.aaa.entity;publicclassProgram{

public static void main(String[] args) {

Calcal=(inta,intb)->{

returna+b;};System.out.println(cal.add(1,2));}}interfaceCal{

int add(int a,int b);}

lambda表达式写法

如下lambda表达式:

(inta,intb)->{

returna+b;}

如上,本质是一个函数。

一般的函数如下:

int add(int a,int b){

returna+b;}

有返回值,方法名,参数列表,方法体

lambda表达式只有参数列表 和方法体 :

(参数列表) ->{

方法体;}

2. Lambda表达式语法

总共6种情况,接口方法无返回值和有返回值分2种,其中无参数、单个参数和多个参数又分3种情况。

来看示例代码:

publicclassTest{

public static void main(String[] args) {

I01i01=()->{

System.out.println("无返回值、无参数");};I02i02=(inta)->{

System.out.println("无返回值,单个参数。a="+a);};I03i03=(inta,intb)->{

System.out.println("无返回值,多个参数。a="+a+",b="+b);};I04i04=()->{

System.out.println("有返回值、无参数");return4;};I05i05=(inta)->{

System.out.println("有返回值,单个参数。a="+a);return5;};I06i06=(inta,intb)->{

System.out.println("有返回值,多个参数。a="+a+",b="+b);return6;};i01.method();i02.method(5);i03.method(5,10);System.out.println(i04.method());System.out.println(i05.method(5));System.out.println(i06.method(5,10));}}interfaceI01{

void method();}interfaceI02{

void method(int a);}interfaceI03{

void method(int a, int b);}interfaceI04{

int method();}interfaceI05{

int method(int a);}interfaceI06{

int method(int a, int b);}

输出:

无返回值、无参数

无返回值,单个参数。a=5

无返回值,多个参数。a=5,b=10

有返回值、无参数

4

有返回值,单个参数。a=5

5

有返回值,多个参数。a=5,b=10

6

3. 函数式接口(Functional Interface)

Java 8为了使现有的函数更加友好地支持Lambda表达式,引入了函数式接口的概念。

函数式接口本质上是一个仅有一个抽象方法的普通接口,所以又叫SAM接口(Single Abstract Method Interface)。

函数式接口在实际使用过程中很容易出错,比如某人在接口定义中又增加了另一个方法,则该接口不再是函数式接口,此时将该接口转换为Lambda表达式会报错。为了克服函数式接口的脆弱性,并且能够明确声明接口是作为函数式接口的意图,Java 8增加了**@FunctionalInterface**注解来标注函数式接口。

使用@FunctionalInterface注解标注的接口必须是函数式接口,也就是说该接口中只能声明一个抽象方法,如果声明多个抽象方法就会报错。但是默认方法和静态方法不属于抽象方法,因此在函数式接口中也可以定义默认方法和静态方法。

比如这样声明一个函数式接口是被允许的:

@FunctionalInterfaceinterface InterfaceDemo {

void method(int a);static void staticMethod() {

...}default void defaultMethod() {

...}}

@FunctionalInterface注解不是必须的,如果一个接口符合"函数式接口"的定义,那么加不加该注解都没有影响。当然加上该注解能够更好地让编译器进行检查,也能提高代码的可读性。

4. Lambda表达式精简语法

参数类型可以省略

比如I02 i02 = (int a) -> {System.out.println(...);}; 可以写成I02 i02 = (a) -> {System.out.println(...);};

假如只有一个参数,那么()括号可以省略

比如I02 i02 = (a) -> {System.out.println(...);}; 可以写成I02 i02 = a -> {System.out.println(...);};

假如方法体只有一条语句,那么语句后的;分号和方法体的{}大括号可以一起省略

比如I02 i02 = a -> {System.out.println(...);}; 可以写成I02 i02 = a -> System.out.println(...);

如果方法体中唯一的语句是return返回语句,那么在省略第3种情况的同时,return也必须一起省略

比如I05 i05 = a -> {return 1;}; 可以写成I05 i05 = a -> 1;

5. 方法引用(Method Reference)

在Java 8中可以用方法引用来进一步简化Lambda表达式。(虽然两者在底层实现原理上略有不同,但在实际使用中完全可以视为等价)

有时候多个Lambda表达式的实现函数是一样的,我们可以封装成一个通用方法,再通过方法引用来实现接口。

5.1 方法引用语法

如果是实例方法:对象名::实例方法名

如果是静态方法:类名::实例方法名

如果是构造方法:类名::new

5.1实例方法引用

来看示例代码:

publicclass Test {

public void eat(int a) {

System.out.println("吃东西。"+"a="+a);}public static void main(String[] args) {

//Lambda表达式写法:Dogdog1=(a)->System.out.println("吃东西。"+"a="+a);Catcat1=(a)->System.out.println("吃东西。"+"a="+a);dog1.doSomething(5);cat1.doSomething(5);//方法引用写法:Testtest=newTest();Dogdog2=test::eat;Catcat2=test::eat;dog2.doSomething(10);cat2.doSomething(10);}}@FunctionalInterfaceinterface Dog {

void doSomething(int a);}@FunctionalInterfaceinterface Cat {

void doSomething(int a);}

输出结果:

吃东西。a=5

吃东西。a=5

吃东西。a=10

吃东西。a=10

5.2 构造方法引用

如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现(比如说接口方法与这个构造方法的参数个数、参数类型和返回值都对的上),那么就可以使用构造方法引用。

代码如下:

publicclass Test {

public void eat(int a) {

System.out.println("吃东西。"+"a="+a);}public static void main(String[] args) {

//Lambda表达式写法:DogServicedogService1=(name,age)->newDog(name,age);System.out.println(dogService1.getDog("大狗",5));//方法引用写法:DogServicedogService2=Dog::new;System.out.println(dogService2.getDog("二狗",3));}}@FunctionalInterfaceinterface DogService {

Dog getDog(String name, int age);}class Dog {

Stringname;intage;public Dog(String name, int age) {

this.name=name;this.age=age;}@Overridepublic String toString() {

return"Dog{"+"name='"+name+'\''+", age="+age+'}';}}

结果:

Dog{

name='大狗',age=5}Dog{

name='二狗',age=3}

你可能感兴趣的:(Java的lambda表达式)