• 基于Spring Boot应用@FunctionalInterface注解


    记录:291

    场景:为了理解和应用@FunctionalInterface注解。@FunctionalInterface是Java语言规范定义函数式接口的注解。它作用在只有一个抽象方法的接口。默认方法(default定义的方法)、静态方法、覆盖Object的方法(比如:boolean equals(Object obj))不计入抽象方法中。

    版本:

    1. JDK 1.8
    2. Spring Boot 2.6.3

    一、理解函数式接口

    (1)@FunctionalInterface是Java语言规范定义函数式接口的注解。

    (2)@FunctionalInterface作用在只有一个抽象方法的接口上。不能作用在annotation type, enum,class上。

    (3)默认方法(default定义的方法)、静态方法、覆盖Object的方法(比如:boolean equals(Object obj))不算抽象方法。

    (4)创建函数式接口实例方式,包括lambda表达式、方法引用、构造函数引用。

    二、@FunctionalInterface的定义

    @FunctionalInterface在jdk中位置:java.lang.FunctionalInterface。

    jdk中的定义:

    1. // Since:1.8
    2. @Documented
    3. @Retention(RetentionPolicy.RUNTIME)
    4. @Target(ElementType.TYPE)
    5. public @interface FunctionalInterface {}

    三、应用@FunctionalInterface

    在Java中的接口interface可以没有方法、只有一个方法、有多个方法等场景。

    使用@FunctionalInterface注解到interface上,那么接口必须有且只能有一个抽象方法。如果没有一个抽象方法、或者有多个抽象方法情况下,编译器会提示报错。

    1.函数式接口(抽象方法无入参)

    1.1定义函数式接口Executable01

    Executable01只有一个抽象方法且无入参。

    1. @FunctionalInterface
    2. public interface Executable01 {
    3. void execute();
    4. }

    1.2应用函数式接口Executable01

    在main函数中应用Executable01。

    (1)使用匿名类方式调用接口。

    (2)使用lambda表达式调用接口。

    (3)实现Executable01接口,使用构造函数创建对象调用接口。

    1. public class FunctionalPractice01 {
    2. public static void main(String[] args) {
    3. // 1. 使用匿名类方式调用接口
    4. f1(new Executable01() {
    5. @Override
    6. public void execute() {
    7. System.out.println("使用匿名类调用函数式接口.");
    8. }
    9. });
    10. // 2. 使用lambda表达式调用接口
    11. f1(() -> {
    12. System.out.println("使用lambda表达式调用函数式接口.");
    13. });
    14. // 3. 实现Executable01接口,使用构造函数创建对象调用接口
    15. f1(new Executable01Impl());
    16. }
    17. public static void f1(Executable01 exe01) {
    18. System.out.println("f1开始...");
    19. exe01.execute();
    20. System.out.println("f1结束...");
    21. }
    22. public static class Executable01Impl implements Executable01 {
    23. @Override
    24. public void execute() {
    25. System.out.println("实现Executable01接口,使用构造函数创建对象调用接口.");
    26. }
    27. }
    28. }

    2.函数式接口(抽象方法有入参)

    2.1定义函数式接口Executable02

    Executable02只有一个抽象方法且有入参。

    1. @FunctionalInterface
    2. public interface Executable02 {
    3. void execute(String cityName);
    4. }

    2.2应用函数式接口Executable02

    在main函数中应用Executable02。

    (1)使用匿名类方式调用接口。

    (2)使用lambda表达式调用接口。

    (3)实现Executable02接口,使用构造函数创建对象调用接口。

    1. public class FunctionalPractice02 {
    2. public static void main(String[] args) {
    3. // 1. 使用匿名类方式调用接口
    4. f1(new Executable02() {
    5. @Override
    6. public void execute(String cityName) {
    7. System.out.println("使用匿名类调用函数式接口.");
    8. System.out.println("接收入参,城市名称: " + cityName);
    9. }
    10. }, "杭州");
    11. // 2. 使用lambda表达式调用接口(cityName,代表抽象方法的入参)
    12. f1((cityName) -> {
    13. System.out.println("使用lambda表达式调用函数式接口.");
    14. System.out.println("接收入参,城市名称: " + cityName);
    15. }, "北京");
    16. // 3. 实现Executable02接口,使用构造函数创建对象调用接口
    17. f1(new FunctionalPractice02.Executable02Impl(), "厦门");
    18. }
    19. public static void f1(Executable02 exe02, String cityName) {
    20. System.out.println("f1开始...");
    21. exe02.execute(cityName);
    22. System.out.println("f1结束...");
    23. }
    24. public static class Executable02Impl implements Executable02 {
    25. @Override
    26. public void execute(String cityName) {
    27. System.out.println("实现Executable01接口,使用构造函数创建对象调用接口.");
    28. System.out.println("接收入参,城市名称: " + cityName);
    29. }
    30. }
    31. }

    3.函数式接口包括多个方法

    函数式接口包括多个方法,使用@FunctionalInterface后,抽象方法只能有一个。

    3.1定义函数式接口Executable03

    Executable03包含多个方法。

    (1)抽象方法。

    (2)默认方法。

    (3)静态方法。

    (4)equals是重写了Object的equals,不计入抽象方法。

    1. @FunctionalInterface
    2. public interface Executable03 {
    3. // 1.抽象方法,且只有一个
    4. void execute();
    5. // 2.默认方法
    6. default void execute01(){
    7. System.out.println("函数式接口的默认(default)方法.");
    8. }
    9. // 3.静态方法
    10. static void execute02(){
    11. System.out.println("函数式接口的静态(static)方法.");
    12. }
    13. // 4. equals是重写了Object的equals,不计入抽象方法
    14. boolean equals(Object obj);
    15. }

    3.2应用函数式接口Executable03

    在main函数中应用Executable03。

    (1)使用lambda表达式调用接口

    1. public class FunctionalPractice03 {
    2. public static void main(String[] args) {
    3. f1(()->{
    4. System.out.println("函数式接口的抽象(abstract)方法.");
    5. });
    6. }
    7. public static void f1(Executable03 exe03) {
    8. System.out.println("f1开始...");
    9. // 1.抽象方法
    10. exe03.execute();
    11. // 2.默认方法
    12. exe03.execute01();
    13. // 3.静态方法
    14. Executable03.execute02();
    15. System.out.println("f1结束...");
    16. }
    17. }

    四、小结

    1.应用小结

    使用@FunctionalInterface注解到Interface中,最大特点就是函数式接口的中这个抽象方法,使用者可以按需定义方法内的具体业务实现。将关注点只需聚焦到这一个抽象方法,其它事情交给Java底层去做。

    2.jdk中函数式接口例子

    在jdk 1.8中的java.util.function包中定义了很多函数式接口,这是研究@FunctionalInterface注解的很好素材。

    以下,随机摘取了几个函数式接口,具体请移步jdk 1.8及其以上版本源码或者操作手册。

    1. java.util.function.BiConsumer
    2. java.util.function.Consumer
    3. java.util.function.Function
    4. java.util.function.DoubleFunction
    5. java.util.function.IntFunction
    6. java.util.function.Predicate

    以上,感谢。

    2022年8月18日

  • 相关阅读:
    Prompt工程师指南[从基础到进阶篇]:用于开发和优化提示,以有效地使用语言模型(LMs)进行各种应用和研究主题
    高性能数据访问中间件 OBProxy(六):一文讲透数据路由
    9.8 校招 实习 内推 面经
    静态数码管显示+动态数码管显示——“51单片机”
    (尚硅谷)JavaWeb新版教程08-QQZone项目的实现
    设计模式-工厂方法
    【数据可视化Python库】
    C++ 递归与面向对象编程基础
    LVGL---滚轮(lv_roller)
    Java核心知识:java集合之Map集合
  • 原文地址:https://blog.csdn.net/zhangbeizhen18/article/details/126415297