当前位置: 首页 > news >正文

Java 函数式接口(Functional Interface)

一、理论说明

1. 函数式接口的定义

Java 函数式接口是一种特殊的接口,它只包含一个抽象方法(Single Abstract Method, SAM),但可以包含多个默认方法或静态方法。函数式接口是 Java 8 引入 Lambda 表达式的基础,通过函数式接口可以将行为作为参数传递,实现更简洁、灵活的代码。

2. 核心特性

  • @FunctionalInterface 注解:可选注解,用于标记接口为函数式接口,编译器会检查该接口是否只有一个抽象方法。
  • 与 Lambda 表达式的关系:Lambda 表达式是函数式接口的实例,可直接赋值给函数式接口类型的变量。
  • 内置函数式接口:Java 8 在 java.util.function 包中提供了一系列通用的函数式接口,如 PredicateFunctionConsumer 等。

二、内置函数式接口

Java 8 提供了四大核心函数式接口,覆盖了常见的函数式编程场景:

1. Predicate<T>

接收一个参数,返回布尔值,用于判断条件。

@FunctionalInterface
public interface Predicate<T> {boolean test(T t);
}// 使用示例
Predicate<Integer> isEven = num -> num % 2 == 0;
System.out.println(isEven.test(4)); // 输出: true

2. Function<T, R>

接收一个参数,返回另一个类型的结果,用于类型转换。

@FunctionalInterface
public interface Function<T, R> {R apply(T t);
}// 使用示例
Function<String, Integer> strLength = s -> s.length();
System.out.println(strLength.apply("hello")); // 输出: 5

3. Consumer<T>

接收一个参数,不返回结果,用于消费数据。

@FunctionalInterface
public interface Consumer<T> {void accept(T t);
}// 使用示例
Consumer<String> printer = s -> System.out.println(s);
printer.accept("Hello, World!"); // 输出: Hello, World!

4. Supplier<T>

不接收参数,返回一个结果,用于提供数据。

@FunctionalInterface
public interface Supplier<T> {T get();
}// 使用示例
Supplier<Double> randomSupplier = () -> Math.random();
System.out.println(randomSupplier.get()); // 输出随机数

三、自定义函数式接口

可以通过 @FunctionalInterface 注解定义自己的函数式接口:

@FunctionalInterface
public interface Calculator {int calculate(int a, int b); // 唯一的抽象方法// 默认方法(非抽象)default void printResult(int result) {System.out.println("计算结果: " + result);}
}// 使用 Lambda 表达式实现
Calculator adder = (a, b) -> a + b;
Calculator subtractor = (a, b) -> a - b;System.out.println(adder.calculate(5, 3)); // 输出: 8
adder.printResult(10); // 输出: 计算结果: 10

四、方法引用(Method Reference)

方法引用是 Lambda 表达式的一种简化形式,用于直接引用已存在的方法。

1. 静态方法引用

// Lambda 表达式
Function<String, Integer> parseInt = s -> Integer.parseInt(s);// 方法引用
Function<String, Integer> parseIntRef = Integer::parseInt;

2. 实例方法引用

// Lambda 表达式
Consumer<String> printer = s -> System.out.println(s);// 方法引用
Consumer<String> printerRef = System.out::println;

3. 构造方法引用

// Lambda 表达式
Supplier<List<String>> listSupplier = () -> new ArrayList<>();// 方法引用
Supplier<List<String>> listSupplierRef = ArrayList::new;

五、应用实例

1. 集合过滤(Predicate)

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class FilterExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);// 过滤偶数List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0) // 使用 Predicate.collect(Collectors.toList());System.out.println(evenNumbers); // 输出: [2, 4, 6]}
}

2. 数据转换(Function)

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class MapExample {public static void main(String[] args) {List<String> words = Arrays.asList("hello", "world");// 转换为大写List<String> upperCaseWords = words.stream().map(String::toUpperCase) // 使用 Function.collect(Collectors.toList());System.out.println(upperCaseWords); // 输出: [HELLO, WORLD]}
}

3. 事件处理

@FunctionalInterface
public interface ClickListener {void onClick(String event);
}public class Button {private ClickListener listener;public void setOnClickListener(ClickListener listener) {this.listener = listener;}public void simulateClick() {if (listener != null) {listener.onClick("Button clicked");}}
}// 使用 Lambda 表达式处理事件
Button button = new Button();
button.setOnClickListener(event -> System.out.println("处理事件: " + event));
button.simulateClick(); // 输出: 处理事件: Button clicked

六、面试题

题目:

答案:

七、自我总结

函数式接口是 Java 函数式编程的核心,它结合 Lambda 表达式和方法引用,使代码更简洁、更具表现力。关键要点包括:

  1. 定义规则:函数式接口只能有一个抽象方法,但可以包含默认方法和静态方法。
  2. 内置接口PredicateFunctionConsumer 和 Supplier 覆盖了常见场景。
  3. 方法引用:简化 Lambda 表达式,提高代码可读性。
  4. 与 Stream API 结合:在集合处理中发挥强大作用。

在实际开发中,函数式接口常用于回调、事件处理、集合操作等场景,能够有效减少样板代码,提升开发效率。但需注意避免过度使用复杂的 Lambda 表达式,保持代码的可维护性。

相关文章:

  • 符合Python风格的对象(使用 __slots__ 类属性节省空间)
  • DeepSeek 赋能数字农业:从智慧种植到产业升级的全链条革新
  • Windows 中动态库.dll 的 .lib 文件有什么作用?
  • SOC-ESP32S3部分:10-GPIO中断按键中断实现
  • 什么是模板字符串?比普通字符串的好处
  • mongodb语法$vlookup性能分析
  • YOLO11解决方案之使用 Streamlit 应用程序进行实时推理
  • github公开项目爬取
  • 【博客系统】博客系统第五弹:基于令牌技术实现用户登录接口
  • 【C++/控制台】迷宫游戏
  • SQL每日一练
  • CloudWeGo-Netpoll:高性能NIO网络库浅析
  • python web 开发-Flask-Login使用详解
  • AtCoder AT_abc407_c [ABC407C] Security 2
  • 开发者工具箱-鸿蒙设备信息功能开发实践
  • 神经算子与FNO技术详解
  • 浅析Spring AOP 代理的生成机制
  • 实现Web网站冷启动的全面指南
  • [软件测试_4] 沟通技巧 | 测试用例 | 设计方法
  • 基于cornerstone3D的dicom影像浏览器 第二十二章 mpr + vr
  • 做进口产品的网站好/会计培训班初级费用
  • wordpress网站数据迁移/seo文章是什么意思
  • 东莞疫情政策/seo优化上首页
  • 做网站的注意事项/客户管理软件
  • 手把手教你用动易做网站/百度平台客服
  • 青岛网站建设 上流/湖人最新排名最新排名