函数式接口@FunctionalInterface

388 阅读2分钟

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

前言

函数式接口@FunctionalInterface,我们看一些JUC底层源码的时候很多就用到函数式接口@FunctionalInterface, 了解一下对源码还是很有帮助的。

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

image.png

应用

@FunctionalInterface
public interface FunService {
    void say(String msg);
}
public class FunTest {
    public static void main(String[] args) {
        String msg = "hello";
        FunService funService = msg1 -> {
            System.out.println(msg);
        };

        funService.say(msg);
        funService.say(msg);
        funService.say(msg);
    }
}

image.png

什么是函数式接口(Functional Interface)

其实之前在讲Lambda表达式的时候提到过,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法

这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。

函数式接口用途

它们主要用在Lambda表达式和方法引用(实际上也可认为是Lambda表达式)上。

常见的lambda表达式

public class FunTest {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        User user = new User();
        user.setId(1L);
        user.setAge(18);
        user.setName("小明");
        userList.add(user);
        User user1 = new User();
        user1.setId(2L);
        user1.setAge(19);
        user1.setName("小张");
        userList.add(user1);
        User user2 = new User();
        user2.setId(3L);
        user2.setAge(17);
        user2.setName("小小");
        userList.add(user2);
        // 对象转换为map
        Map<Long, User> map = userList.stream().collect(Collectors.toMap(User::getId, account -> account));
        System.out.println(JSON.toJSONString(map));

        // 获取ids 去重
        Set<Long> ids = userList.stream().map(User::getId).collect(Collectors.toSet());
        System.out.println(ids);

        // 条件过滤
        List<User> list = userList.stream().filter(e -> e.getAge() > 17L).collect(Collectors.toList());
        System.out.println(JSON.toJSONString(list));
    }
}

JDK中的函数式接口举例

java.lang.Runnable,
java.awt.event.ActionListener, 
java.util.Comparator,
java.util.concurrent.Callable
java.util.function包下的接口,如Consumer、Predicate、Supplier等

当然比如常见的工具类Hutool中也大量应用了函数式接口, 各有利弊,函数式接口可以使代码更加简洁,但是用不好或者没有相关的知识就比较晦涩难懂。