• java代码之美(14)---Java8 函数式接口


    Java8 函数式接口

    之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda

    函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加简洁。

    一、概念

    1、什么是函数式接口

    概念 所谓的函数式接口, 当然首先是一个接口, 然后就是在这个接口里面 只能有一个抽象方法

    有关函数式接口,有个专门的注解叫:@FunctionalInterface。该注解主要特点有:

    1、该注解只能标记在"有且仅有一个抽象方法"的接口上,表示函数式接口。
    2、JDK8接口中的静态方法和默认方法,都不算是抽象方法。
    3、接口默认继承 java.lang.Object,所以如果接口显示声明覆盖了Object中的方法,那么也不算抽象方法。
    4、允许java.lang.Object中的public方法
    5、该注解不是必须的,如果一个接口符合"函数式编程"定义,那么加不加该注解都没有影响。加上该注解能够 更好地让编译器进行检查,
    如果编写的不是函数式接口,但是加上了@FunctionalInterface 那么编译器会报错。
    

    2、示例

    1. 正确示例
    /**
     * 函数式接口注解
     */
    @FunctionalInterface
    public interface PersonInterface { 
        /**
         * 1、仅有一个抽象方法
         */
         void say();
         
        /**
         * 2、java.lang.Object中的方法不算
         */
        @Override
         boolean equals(Object var1);
        
        /**
         * 3、java8 接口才可以有默认的方法实现 前提是方法名称必须使用default关键字修饰
         */
         default void defaultMethod() {
            System.out.println("haha");
        }
        
        /**
         * 4、静态方法
         */
         static void staticMethod() {
        }
    }
    
    1. 错误示例

    加上@FunctionInterface,就代表该接口是函数式接口,只能有一个抽象方法,如果有多个编译时就会直接报错。

    3、为什么只能有一个抽象方法

    其实这个问题很好去理解,上面说了函数式接口主要是为Lambda语法服务的,为了让代码看去更加简洁。

    下面通过示例来说明

         public static void main(String[] args) {
           //上面的接口 通过Lambda表达式重新 say方法 
            PersonInterface inter = () -> System.out.println("我说什么好呢?");
            inter.say();
            //控制台输出: 我说什么好呢?
        }
    

    通过 函数式接口 + Lambda表达式 让代码看去变的简洁,而这里的关键点在于:

     ()->{} 就是代表对say()方法的重写
    

    如果你有个多个抽象方法, 那么()-> {} 这种写法,编译器就不知道这是重写的哪个方法了。所以这就是为什么只能有一个抽象方法的原因。


    二、综合示例

    这里再举一个综合示例,来方便理解它们。

    自定义函数式接口

    /**
      * 自定义函数TestFunction,提供handler接口, 传入的是A,返回的是B
      */
    @FunctionalInterface
    public interface MyFunction<A, B> {
    
        /**
          * @Description: 传入的是A 返回的是B
          */
        B handler(A a, A a1);
    }
    

    Student对象

    public class Student {
        /**
         * 姓名
         */
        private String name;
        /**
         * 年龄
         */
        private Integer age;
        
        //省略 set get toString 全参数构造函数 无参构造函数
      }
    

    测试类

       public static void main(String[] args) {
            //1、求和 传入Integer返回Integer类型
            MyFunction<Integer, Integer> myFunction1 = (x, y) -> {
                //返回总和
                return x + y;
            };
            Integer count = myFunction1.handler(5, 10);
            System.out.println("输出总和为:" + count);
    
    
            //2、求和 传入Integer返回String类型
            MyFunction<Integer, String> myFunction2 = (x, y) -> {
                //返回总和
                return x + " + " + y + " = " + (x + y);
            };
            System.out.println(myFunction2.handler(5, 10));
    
    
            //3、对象处理 过滤对象
            List<Student> students = Arrays.asList(new Student("小明", 3), new Student("小白", 13), new Student("小黄", 18));
            MyFunction<Integer, List<Student>> myFunction3 = (x, y) -> {
                //这里通过java8 的stream来过滤 年龄大于x 且小于y的对象
                List<Student> studentList = students.stream().filter(student -> student.getAge() > x && student.getAge() < y).collect(Collectors.toList());
                return studentList;
            };
    
            List<Student> list = myFunction3.handler(5, 15);
            //遍历集合 输出对象
            list.forEach(x -> System.out.println(x));
        }
    

    运行结果

    从运行结果可以很明显看出,集合对象经过过滤只剩下一个满足条件的了。



    你如果愿意有所作为,就必须有始有终。(24)
    
  • 相关阅读:
    UWP中的消息提示框(二)
    UWP中的消息提示框(一)
    使用批处理编写ORACLE设置
    程序员那些事儿
    “程序已停止工作”问题的解决方法
    《第一行代码--Android》阅读笔记之数据持久化
    《第一行代码--Android》阅读笔记之广播
    《第一行代码--Android》阅读笔记之界面设计
    《第一行代码--Android》阅读笔记之Activity
    WinForm中为按钮添加键盘快捷键,超简单,亲测有效
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/12046505.html
Copyright © 2020-2023  润新知