• java8新特性学习:函数式接口


    本文概要

    1. 什么是函数式接口?
    2. 如何定义函数式接口?
    3. 常用的函数式接口
    4. 函数式接口语法注意事项
    5. 总结

    1. 什么是函数式接口?

    函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口(Single Abstract Method),在这个接口里面只能有一个抽象方法。

    当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。Lambda表达式只是语法糖,我们只要理解函数式接口,才能读懂和用好Lambda表达式。

    2. 如何定义函数式接口?

    @FunctionalInterface
    public interface FunctionDemo {
    
        void get(String str);
    }
    
    FunctionDemo fd = str -> System.out.println("Hello " + str);
    

    3. 常用的函数式接口

    使用Lambda表达式,一定有函数式接口的支持;但是如果我们每一个Lambda表达式都要自己创建一个接口,
    这样很造成很大的不便。为了避免重复造轮子,java8常用的函数式接口都帮我们定义好,拿来直接使用即可。

    如果这些常用的接口不能满足需求时,这时才需要 自定义函数式接口。

    下面是我们常用的几类函数式接口:

    • 消费性函数式接口

    特点:接受一个或者多个参数,没有返回值

    • 供给型函数式接口

    特点:没有参数(无参),提供返回值

    • 函数型函数式接口

    特点:接收一个或者多个参数,有返回值

    • 断定性函数式接口

    特点:接收一个或者多个参数,返回一个boolean类型

    @Test
    public void testCoreInter(){
        /**
         * @name 消费型接口
         * @use Consumer<T>
         * @param T 传入参数
         * @fun 接受一个参数 无返回值
         * */
        Consumer<String> con=(str)->System.out.println(str);
        con.accept("我是消费型接口!");
    
        /**
         * @name 供给型接口
         * @use Supplier<R>
         * @param R 返回值类型
         * @fun 无参数 有返回值
         * */
        Supplier<Date> supp=()-> new Date();
        Date date=supp.get();
        System.out.println("当前时间:"+date);
    
        /**
         * @name 函数型接口
         * @use Function<T,R>
         * @param T 传入参数
         * @return R 返回值类型
         * @fun 接受一个参数 有返回值
         * */
        Function<String, String> fun=(str)->"hello,"+str;
        String str=fun.apply("张俊强");
        System.out.println(str);
        
        /**
         * @name 断定型接口
         * @use Predicate<T>
         * @param T 传入参数
         * @return Boolean 返回一个Boolean型值
         * @fun 接受一个参数 返回Boolean型值
         * */
        Predicate<Integer> pre=(num)->num>0;
        Boolean flag=pre.test(10);
        System.out.println(flag);
    }
    

    比如方法foreach(),入参为Consumer

    default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    

    4. 函数式接口语法注意事项

    从SAM原则上讲,这个接口中,只能有一个函数需要被实现,但是也可以有如下例外:

    • 默认方法:必须用default修饰,且只能是public,默认也是public。

    它也是作为一种向后兼容能力而出现,旧的接口也能用到Lambda表达式中。例如,List或Collection接口是没有forEach方法的声明的。Java 8引入默认方式使得List和Collection接口能够拥有forEach方法的默认实现。实现了这些接口的类也不必再实现相同的功能了。

    语法如下所示:

    @FunctionalInterface  
    interface A {  
         default void test() {  
               System.out.println("接口A的默认方法");  
         }  
         void test1();  
    }  
    
    • 静态方法

    函数式接口中可以有静态方法,一个或者多个静态方法不会影响SAM接口成为函数式接口,并且静态方法可以提供方法实现

    @FunctionalInterface  
    interface TestStaticMethod {  
         //这是一个抽象方法  
         void test();  
         //静态方法,不是抽象方法  
         static void test1() {  
               System.out.println("接口里的静态方法!");  
         }  
    }  
    

          
          
          

    • 如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
     If an interface declares an abstract method overriding one of the public methods of {@code java.lang.Object},
     that also doesnot count toward the interface's abstract method count
     since any implementation of the interface will have an implementation from {@code java.lang.Object} or elsewhere.
    
    
    @FunctionalInterface
    public interface DemoFunctionalInterface{
        void action();
    
        //Object's public methods
        String toString();
        int hashCode();
        boolean equals(Object o);
    }
    
    
    • 注解@FunctionalInterface不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

    5. 总结

    • 函数式接口只能包含一个抽象方法
    • 函数式接口可以包含Object类中所有public修饰的方法
    • 函数工接口可以包含一个或多个静态方或默认方法

    参考文献


    tips:本文属于自己学习和实践过程的记录,很多图和文字都粘贴自网上文章,没有注明引用请包涵!如有任何问题请留言或邮件通知,我会及时回复。

  • 相关阅读:
    String、Stringbuilder、StringBuffer之间的练习与区别
    JAVA——重点非阻塞模型:NIO模型及IO操作步骤
    JAVA——IO模型分类
    SpringBoot(六) SpringBoot使用汇总(持续更新)
    Java高级(一) Future机制
    SpringBoot(二) 事务
    Java8(七) 新的DateTime API
    Java8(六) Optional
    Java8(五) 接口默认方法
    Java8(四) StreamAPI
  • 原文地址:https://www.cnblogs.com/small-k/p/8372511.html
Copyright © 2020-2023  润新知