基于Spring Boot应用@FunctionalInterface注解

记录:291

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

版本:

JDK 1.8
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中的定义:

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

三、应用@FunctionalInterface

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

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

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

1.1定义函数式接口Executable01

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

@FunctionalInterface
public interface Executable01 {
    void execute();
}

1.2应用函数式接口Executable01

在main函数中应用Executable01。

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

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

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

public class FunctionalPractice01 {
  public static void main(String[] args) {
  
    // 1. 使用匿名类方式调用接口
    f1(new Executable01() {
        @Override
        public void execute() {
            System.out.println("使用匿名类调用函数式接口.");
        }
    });
	
    // 2. 使用lambda表达式调用接口
    f1(() -> {
        System.out.println("使用lambda表达式调用函数式接口.");
    });
	
    // 3. 实现Executable01接口,使用构造函数创建对象调用接口
    f1(new Executable01Impl());
  }
  
  public static void f1(Executable01 exe01) {
    System.out.println("f1开始...");
    exe01.execute();
    System.out.println("f1结束...");
  }
  
  public static class Executable01Impl implements Executable01 {
    @Override
    public void execute() {
        System.out.println("实现Executable01接口,使用构造函数创建对象调用接口.");
    }
  }
}

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

2.1定义函数式接口Executable02

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

@FunctionalInterface
public interface Executable02 {
  void execute(String cityName);
}

2.2应用函数式接口Executable02

在main函数中应用Executable02。

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

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

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

public class FunctionalPractice02 {
  public static void main(String[] args) {
  
    // 1. 使用匿名类方式调用接口
    f1(new Executable02() {
      @Override
      public void execute(String cityName) {
        System.out.println("使用匿名类调用函数式接口.");
        System.out.println("接收入参,城市名称: " + cityName);
      }
    }, "杭州");
  
    // 2. 使用lambda表达式调用接口(cityName,代表抽象方法的入参)
    f1((cityName) -> {
      System.out.println("使用lambda表达式调用函数式接口.");
      System.out.println("接收入参,城市名称: " + cityName);
    }, "北京");
  
    // 3. 实现Executable02接口,使用构造函数创建对象调用接口
    f1(new FunctionalPractice02.Executable02Impl(), "厦门");
  
  }
  
  public static void f1(Executable02 exe02, String cityName) {
    System.out.println("f1开始...");
    exe02.execute(cityName);
    System.out.println("f1结束...");
  }
  
  public static class Executable02Impl implements Executable02 {
  
   @Override
   public void execute(String cityName) {
    System.out.println("实现Executable01接口,使用构造函数创建对象调用接口.");
    System.out.println("接收入参,城市名称: " + cityName);
  
   }
  }
}

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

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

3.1定义函数式接口Executable03

Executable03包含多个方法。

(1)抽象方法。

(2)默认方法。

(3)静态方法。

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

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

3.2应用函数式接口Executable03

在main函数中应用Executable03。

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

public class FunctionalPractice03 {
  public static void main(String[] args) {
    f1(()->{
        System.out.println("函数式接口的抽象(abstract)方法.");
    });
  }
  
  public static void f1(Executable03 exe03) {
    System.out.println("f1开始...");
    // 1.抽象方法
    exe03.execute();
    // 2.默认方法
    exe03.execute01();
    // 3.静态方法
    Executable03.execute02();
    System.out.println("f1结束...");
  }
}

四、小结

1.应用小结

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

2.jdk中函数式接口例子

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

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

java.util.function.BiConsumer
java.util.function.Consumer
java.util.function.Function
java.util.function.DoubleFunction
java.util.function.IntFunction
java.util.function.Predicate

以上,感谢。

2022年8月18日

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值