JAVA8新特性--Lambda表达式与函数式接口

先介绍下Lambda表达式,函数式接口会在穿插的例子后面介绍。
Lambda:允许把函数作为一个方法的参数(函数作为参数传递进方法中),Lambda表达式最终返回的是函数式接口的一个对象实例,因此需要依赖于函数式接口。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
语法:

(parameters) -> expression

(parameters) ->{ statements; }

语法总共分为三部分

  • 入参 :即传入的参数列表
  • 符号 ->
  • 主体 : 即代码语句块

Lambda的四个特性:

  • a.可选类型声明:传入的参数可以不用声明类型,编译器可以自动识别参数类型。
  • b.可选的参数圆括号:只有一个传入参数时可以省略圆括号(必须同时省略参数类型),多个参数时必须使用圆括号。
  • c.可选的大括号:如果主体只有一个语句,可以不需要使用大括号。
  • d.可选的返回关键字”return”:如果需要返回值主体只有一个表达式则可以同时省略大括号和”return”关键字,编译器会自动将结果作为返回值,如果使用了大括号则返回值不能省略”return”关键字。

函数式接口只包含一个抽象方法的接口,这个抽象方法定义了这个接口的目标及用途,同时JAVA8中还引用了一个注解来标识函数式接口:@FunctionalInterface。
@FunctionalInterface:可以被在任何的函数式接口上,但是函数式接口不一定需要此注解。当使用@FunctionalInterface定义函数式接口时,如果在接口定义多个(非静态和非默认)方法,则会编译报错,但是有个例外:函数式接口中可以定义java.long.Object类中的所有方法,函数式接口中可以有多个静态方法和默认方法。

下面通过一些例子来介绍Lambda的标准写法及使用四个特性的简化写法。
先定义两个函数式接口:

//FunctionalInterface声明一个接口为函数式接口,此注解非必须
@FunctionalInterface
interface TestService {
    int sum(int a,int b);

    //java.long.Object的方法
    boolean equals(Object obj);
    //java.long.Object的方法
    String toString();

    //默认方法
    default void getStr(String str){
        System.out.println("str="+str);
    }
    //静态方法
    static void getName(String name){
        System.out.println("name="+name);
    }
}

//此函数式接口不使用注解
interface BService {
    void sum(String b);
}

Lambda的完整写法为

TestService testService = (int a, int b) -> {
    return a * b *3;
};
System.out.println("testService result " + testService.sum(2,3));

输出为

testService result 18

使用特性a的写法

TestService testServiceA = (a, b) -> { return a * b *3; };
System.out.println("testServiceA result " + testServiceA.sum(2,3));

输出为

testServiceA result 18

使用特性b的写法

BService testServiceB = b -> { System.out.println("test B = " + b); };
testServiceB.sum("参数B");

输出为

test B = 参数B

使用特性c的写法

BService testServiceC = c ->  System.out.println("test C = " + c);
testServiceC.sum("参数C");

输出为

test C = 参数C

使用特性d的写法

TestService testServiceD = (a, b) ->  a * b *3;
System.out.println("testServiceD result " + testServiceD.sum(2,3));

输出为

testServiceD result 18


通过Lambda的四个特性我们基本把它的各种书写方式都描述了一下,但是没能很直观的描述出把函数作为一个方法的参数,因此再找个直观点的例子:
在java7中我们对集合排序通常是使用Collections的sort方法并且传入一个Comparator的对象实例,像这样写:

List list = Arrays.asList("a", "b", "d");
Collections.sort(list, new Comparator() {
    public int compare(String o1, String o2) {
        return (o2).compareTo(o1);
    }
});

如果是在java8中,那就可以使用Lambda,像这样写:

List list = Arrays.asList("a", "b", "d");
Collections.sort(list,( e1, e2 ) -> e1.compareTo( e2 ));

这样是不是就能很直观的看到Lambda的用法。

至于函数式接口中是否使用注解@FunctionalInterface,则看具体使用场景。

  • 如果使用注解@FunctionalInterface,在编写接口过程中如果有不符合函数式接口规范的地方就会直接编译报错

  • 如果不使用注解@FunctionalInterface,在编写接口过程中即使有不符合函数式接口规范的地方也不会报错,只会在使用Lambda表达式的地方报错

你可能感兴趣的:(JAVA)