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

Java8 函数式接口

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

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

1、概念

一、什么是函数式接口

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

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

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

二、示例

1) 正确示例函数式编程

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

2) 错误示例函数

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

三、为何只能有一个抽象方法

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

下面经过示例来讲明code

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

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

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

若是你有个多个抽象方法, 那么()-> {} 这种写法,编译器就不知道这是重写的哪一个方法了。因此这就是为何只能有一个抽象方法的缘由。


2、综合示例

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

自定义函数式接口

/**
  * 自定义函数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) {
        //一、求和 传入Integer返回Integer类型
        MyFunction<Integer, Integer> myFunction1 = (x, y) -> {
            //返回总和
            return x + y;
        };
        Integer count = myFunction1.handler(5, 10);
        System.out.println("输出总和为:" + count);


        //二、求和 传入Integer返回String类型
        MyFunction<Integer, String> myFunction2 = (x, y) -> {
            //返回总和
            return x + " + " + y + " = " + (x + y);
        };
        System.out.println(myFunction2.handler(5, 10));


        //三、对象处理 过滤对象
        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)
相关文章
相关标签/搜索