【Java8 新特性 2】函数式接口 + Lamda表达式推导过程

    技术2022-07-17  81

    一、函数式接口简介

    函数式接口是 Java8 引入的一个新特性,是一种特殊的接口:SAM类型的接口(Single Abstract Method),但本质上还是接口。相比较于其他接口,函数式接口有且只能有一个抽象方法。只要接口中出现多个抽象方法,那么就不能称之为函数式接口,运行的时候就会报错。为此 Java8 提供了一个新的注解@FunctionalInterface,如果接口被这个注解标注,就说明该接口是函数式接口,如果有多于一个的抽象方法,在编译的时候就会报错。但是这个注解不是必需的,只要接口符合函数式接口的定义,那么这个接口就是函数式接口。

    简单来说,一个接口有且只有一个抽象方法,即函数式接口。

    二、函数式接口特性

    原则上讲,函数式接口中有且只能有一个抽象方法。但是在 Java8 之后接口中也是可以定义方法的:默认方法和静态方法,这两种方法的定义并不会影响函数式接口的定义,可以随意使用。即:

    1、静态方法

    接口中可以有一个或多个静态方法,这不会影响到函数式接口的定义。

    2、default方法

    在 Java8 之后,接口允许定义由 default 修饰的默认方法,并且不强制实现类重写此方法,这些方法也不会影响到函数式接口的定义。

    默认方法不能被直接调用,可以由实现类调用。

    注意事项

    (1)当一个实现类实现了多个接口,多个接口里都有相同的默认方法时,实现类必须重写该默认方法,否则编译错误。

    (2)实现类使用super关键字指定使用哪个接口的默认方法。

    3、函数式接口支持继承

    函数式接口支持继承,可以继承多个父接口,但是每个父接口只能有一个抽象方法,且必须是相同的抽象方法。

    三、函数式接口的意义

    我是这么理解的,java是面向对象的,但是为了写起来方便,需要向一个方法传递一个方法,但是实际上并不能传递方法,而是传递了只有一个抽象方法的接口的实现类的对象,这样就做到类似传递方法了,其实lanmada就是一个对象

    四、四种核心的函数式接口

    1、功能性接口Function  

    接收一个功能参数t,并返回一个功能结果R。

    package java.util.function; import java.util.Objects; @FunctionalInterface public interface Function<T, R> { R apply(T t); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } static <T> Function<T, T> identity() { return t -> t; } }

    2、断言性接口:Predicate

    主要用到test方法 其中参数t为输入参数,如果输入参数符合断言则返回true,否则false

    package java.util.function; import java.util.Objects; @FunctionalInterface public interface Predicate<T> { boolean test(T t); default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate<T> negate() { return (t) -> !test(t); } default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }

    3、供给性接口:Supplier

    不接收任何参数 但有返回值

    @FunctionalInterface public interface Supplier<T> { T get(); }

    4、消费性接口:Consumer   

    只接收一个参数t,但是没有返回值。

    五、Lambda表达式

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

    虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。

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

    简单明了,函数式接口就是为了Lambda 表达式而生的。

    六、Lambda表达式的推导过程

    1、匿名内部类 --> Lambda表达式 --> 简化Lambda表达式

    package java8.lamda; public class LamdaTest { public static void main(String[] args) { //匿名内部类 IStudent student = new IStudent() { @Override public void study(String technology,int time) { System.out.println("匿名内部类,"+technology+time); } }; student.study("java",8); //Lambda表达式改造(将类名和方法名去掉) IStudent student1 = (String technology,int time)->{ System.out.println("Lambda表达式改造(将类名和方法名去掉)"+technology+time); }; student1.study("java",8); //一级进化(去掉数据类型) IStudent student2 = ((technology, time) -> { System.out.println("一级进化(去掉数据类型)"+technology+time); }); student2.study("java",8); //二级进化(简化括号),一般进行一次进化就可以了,二级进化没必要 IStudent student3 = ((technology, time) -> System.out.println("二级进化(简化括号)"+technology+time)); student3.study("java",8); } } @FunctionalInterface interface IStudent { void study(String technology,int time); }

    2、控制台输出

     

    上一篇:Java注解深入浅出

    下一篇:【Java8 新特性】Lambda表达式总结(全栈最强,绝对豪横)

    Processed: 0.016, SQL: 9