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

Java常用注解--@FunctionalInterface 函数式接口

文章目录

  • 1 定义要求
  • 2 实现方式
    • 1. Lambda 表达式
    • 2. 方法引用
    • 3. 内置函数式接口
  • 3 自定义函数式接口的典型用途
    • 1 简化回调逻辑
      • 1.1 使用函数式接口简化,
      • 1.2 灵活扩展
    • 2 组合函数
  • 4 实践举例
    • 4.1 资源清理(自动关闭)
    • 4.2 策略模式(动态算法选择)
    • 4.3 流水线处理(链式操作)
    • 4.4 异步任务编排
    • 4.5 条件触发(事件驱动)

1 定义要求

  • 必须是一个接口(interface)。
  • 有且仅有一个抽象方法(允许包含默认方法或静态方法)。
  • 使用 @FunctionalInterface 注解标记,编译器会强制校验是否符合条件。
@FunctionalInterface
public interface StringProcessor {// 唯一抽象方法String process(String input);	// 什么也不干,谁实现的就干什么// 默认方法不计入抽象方法数量default void log(String message) {System.out.println("Log: " + message);}
}

2 实现方式

1. Lambda 表达式

直接通过 Lambda 实现函数式接口

StringProcessor upperCaseProcessor = (input) -> input.toUpperCase();	// 函数式接口的功能被实现为转大写
System.out.println(upperCaseProcessor.process("hello")); // 输出 "HELLO"

2. 方法引用

引用现有方法作为实现:

StringProcessor trimProcessor = String::trim;	// 函数式接口的功能被实现trim
System.out.println(trimProcessor.process("  hello  ")); // 输出 "hello"

3. 内置函数式接口

Java 内置自带的接口(如 Predicate, Function, Consumer):

// 使用 Predicate 过滤数据
Predicate<String> isEmpty = s -> s == null || s.isEmpty();
List<String> nonEmptyList = list.stream().filter(isEmpty.negate()).collect(Collectors.toList());

3 自定义函数式接口的典型用途

1 简化回调逻辑

@FunctionalInterface
public interface OnSuccessCallback {void execute(String result);
}public void fetchData(OnSuccessCallback callback) {// 模拟异步操作new Thread(() -> {String data = "Data loaded";callback.execute(data);}).start();
}// 调用
fetchData(result -> System.out.println("Received: " + result));

如何简化?
对比Java 8之前,回调通常通过匿名内部类实现,代码冗余且不够直观:

// 定义回调接口
public interface Callback {void onSuccess(String data);void onFailure(String error);
}// 使用回调
public void fetchData(Callback callback) {try {String data = "Data loaded";callback.onSuccess(data);} catch (Exception e) {callback.onFailure("Error: " + e.getMessage());}
}// 调用时需实现所有方法(即使不关心某些情况)
fetchData(new Callback() {@Overridepublic void onSuccess(String data) {System.out.println("Received: " + data);}@Overridepublic void onFailure(String error) {// 即使不需要处理失败,也必须实现空方法}
});

问题:必须实现接口所有方法,即使某些场景下不需要全部逻辑。

1.1 使用函数式接口简化,

定义单一职责的接口,通过 @FunctionalInterface 拆分接口,每个接口只关注一个操作

@FunctionalInterface
public interface SuccessCallback {void handleSuccess(String data);
}@FunctionalInterface
public interface FailureCallback {void handleFailure(String error);
}

然后按需传递回调即可:

public void fetchData(SuccessCallback success, FailureCallback failure) {try {String data = "Data loaded";success.handleSuccess(data);} catch (Exception e) {failure.handleFailure("Error: " + e.getMessage());}
}// 调用时只需关注需要的回调(Lambda表达式)
fetchData(data -> System.out.println("Success: " + data),  // 成功回调error -> System.err.println("Failed: " + error)  // 失败回调(可选)
);

优势:
代码简洁:无需冗余的匿名类模板。
按需实现:只传递关心的回调(如失败回调可省略)。
可读性高:Lambda直接表达逻辑意图。

1.2 灵活扩展

  1. 结合默认方法
    为函数式接口添加默认方法,增强功能:
@FunctionalInterface
public interface SuccessCallback {void handleSuccess(String data);// 默认方法:添加日志功能default SuccessCallback withLogging() {return data -> {System.out.println("[Log] Success data: " + data);handleSuccess(data);};}
}// 使用增强的回调
SuccessCallback callback = data -> System.out.println("处理数据: " + data);
fetchData(callback.withLogging(), null);
  1. 支持链式调用
fetchData(data -> processData(data).andThen(() -> logOperation("完成"))
);

2 组合函数

一个接口被实现后,干了很多事

@FunctionalInterface
public interface TextTransformer {String transform(String text);default TextTransformer andThen(TextTransformer after) {return text -> after.transform(this.transform(text));}
}// 使用
TextTransformer upperCase = String::toUpperCase;
TextTransformer addExclamation = s -> s + "!";
TextTransformer combined = upperCase.andThen(addExclamation);
System.out.println(combined.transform("hello")); // 输出 "HELLO!"

4 实践举例

4.1 资源清理(自动关闭)

场景:需要在操作完成后自动释放资源(如文件、数据库连接)。

@FunctionalInterface
public interface ResourceHandler<T> {void handle(T resource) throws IOException;// 封装资源打开和关闭逻辑static <T extends AutoCloseable> void useResource(Supplier<T> resourceSupplier, ResourceHandler<T> handler) throws IOException {try (T resource = resourceSupplier.get()) {handler.handle(resource);}}
}// 使用示例:自动关闭文件流
ResourceHandler.useResource(() -> new FileInputStream("data.txt"), // 资源提供者inputStream -> {byte[] data = inputStream.readAllBytes();System.out.println("读取到 " + data.length + " 字节");} // 处理逻辑(无需手动关闭)
);

优势:将资源获取/释放与业务逻辑解耦,避免忘记关闭资源。

4.2 策略模式(动态算法选择)

场景:根据运行时条件选择不同的处理策略。

@FunctionalInterface
public interface PaymentStrategy {void pay(BigDecimal amount);
}public class PaymentService {private PaymentStrategy strategy;public void setStrategy(PaymentStrategy strategy) {this.strategy = strategy;}public void executePayment(BigDecimal amount) {strategy.pay(amount);}
}// 使用示例:动态切换支付方式
PaymentService service = new PaymentService();// 选择支付宝支付
service.setStrategy(amount -> System.out.println("支付宝支付:" + amount + "元"));
service.executePayment(new BigDecimal("100.00"));// 切换为微信支付
service.setStrategy(amount ->System.out.println("微信支付:" + amount + "元"));
service.executePayment(new BigDecimal("200.00"));

优势:避免继承导致的类膨胀,策略实现更灵活。

4.3 流水线处理(链式操作)

场景:对数据依次进行多个处理步骤(如数据清洗、转换)。

@FunctionalInterface
public interface DataProcessor<T> {T process(T data);// 组合多个处理器default DataProcessor<T> andThen(DataProcessor<T> next) {return data -> next.process(this.process(data));}
}// 定义处理步骤
DataProcessor<String> trimProcessor = String::trim;
DataProcessor<String> upperCaseProcessor = String::toUpperCase;
DataProcessor<String> appendProcessor = s -> s + "!";// 组合流水线
DataProcessor<String> pipeline = trimProcessor.andThen(upperCaseProcessor).andThen(appendProcessor);String result = pipeline.process("  hello  "); // 输出 "HELLO!"

优势:通过链式调用实现可复用的处理流程。

4.4 异步任务编排

场景:多个异步任务需要顺序执行或合并结果

@FunctionalInterface
public interface AsyncTask<T> {CompletableFuture<T> execute();// 组合任务:先执行当前任务,再执行后续任务default <U> AsyncTask<U> thenCompose(Function<T, AsyncTask<U>> next) {return () -> this.execute().thenCompose(result -> next.apply(result).execute());}
}// 示例:异步获取用户信息 → 异步获取订单
AsyncTask<User> fetchUser = () -> userService.getUserAsync(1);
AsyncTask<Order> fetchOrder = user -> orderService.getOrderAsync(user.getId());AsyncTask<Order> combinedTask = fetchUser.thenCompose(fetchOrder);
combinedTask.execute().thenAccept(order -> System.out.println("订单详情:" + order)
);

优势:用声明式语法替代回调地狱(Callback Hell)。

4.5 条件触发(事件驱动)

场景:满足特定条件时触发操作(如监控阈值报警)。

@FunctionalInterface
public interface ConditionTrigger {void triggerIf(Supplier<Boolean> condition, Runnable action);
}// 实现类:定期检查条件
public class SchedulerTrigger implements ConditionTrigger {@Overridepublic void triggerIf(Supplier<Boolean> condition, Runnable action) {ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);scheduler.scheduleAtFixedRate(() -> {if (condition.get()) {action.run();scheduler.shutdown();}}, 0, 1, TimeUnit.SECONDS);}
}// 使用示例:CPU使用率超过80%时报警
SchedulerTrigger trigger = new SchedulerTrigger();
trigger.triggerIf(() -> getCpuUsage() > 80.0, // 条件检测() -> sendAlert("CPU过载!")  // 触发动作
);

优势:将条件检测与响应动作解耦,便于复用。

相关文章:

Java常用注解--@FunctionalInterface 函数式接口

文章目录 1 定义要求2 实现方式1. Lambda 表达式2. 方法引用3. 内置函数式接口 3 自定义函数式接口的典型用途1 简化回调逻辑1.1 使用函数式接口简化&#xff0c;1.2 灵活扩展 2 组合函数 4 实践举例4.1 资源清理&#xff08;自动关闭&#xff09;4.2 策略模式&#xff08;动态…...

Xen Center虚拟机Centos 7.x磁盘扩容

文章目录 概要XenCenter虚拟机操作系统命令概览扩容步骤 概要 适用于Centos 7.x系统磁盘扩容&#xff0c;不区分是否虚拟机或者实体系统 XenCenter 使用Xen Center客户端给对应的虚拟机添加一块磁盘后&#xff0c;启动虚拟机系统在系统中进行扩容 虚拟机操作系统 Centos 7.…...

如何调用 DeepSeek API:详细教程与示例

目录 一、准备工作 二、DeepSeek API 调用步骤 1. 选择 API 端点 2. 构建 API 请求 3. 发送请求并处理响应 三、Python 示例&#xff1a;调用 DeepSeek API 1. 安装依赖 2. 编写代码 3. 运行代码 四、常见问题及解决方法 1. API 调用返回 401 错误 2. API 调用返回…...

MySQL_事务的四大特性

1.事务的什么 在学习MySQL的初期&#xff0c;我们通常都是一个一个sql语句的执行&#xff0c;但是在实际开发过程中&#xff0c;我们经常是多个sql语句一起执行&#xff0c;这种多个sql语句在逻辑上要一起执行的就可以看做是一个事务&#xff0c;组成这个事务的多个sql&#x…...

如何在Jenkins上查看Junit报告

在 Jenkins 上查看 JUnit 报告通常有以下几个步骤&#xff1a; 构建结果页面: 首先&#xff0c;确保你的 Jenkins 构建已经执行完毕&#xff0c;并且成功生成了 JUnit 报告。前往 Jenkins 主页面&#xff0c;点击进入相应的项目或流水线。 构建记录: 选择你想查看的特定构建记…...

【深度学习】计算机视觉(CV)-图像生成-风格迁移(Style Transfer)

风格迁移&#xff08;Style Transfer&#xff09; 风格迁移是一种计算机视觉技术&#xff0c;可以将一张图像的内容和另一张图像的风格融合在一起&#xff0c;生成一张既保留原始内容&#xff0c;又带有目标风格的全新图像&#xff01;这种方法常用于艺术创作、图像增强、甚至…...

Nginx 配置:alias 和 root 的区别

在 Nginx 的配置中&#xff0c;alias 和 root 是两个用于映射文件路径的重要指令。虽然它们的功能表面相似&#xff0c;实际使用中却有显著的差异。如果不清楚两者的用法和特点&#xff0c;可能会导致资源路径错误或访问异常。本文将详细解析它们的区别&#xff0c;并提供实用示…...

深入理解 QObject的作用

QObject 作为 Qt 库中所有对象的基类&#xff0c;其地位无可替代。几乎 Qt 框架内的每一个类&#xff0c;无论是负责构建用户界面的 QWidget&#xff0c;还是专注于数据处理与呈现的 QAbstractItemModel&#xff0c;均直接或间接继承自 QObject。这种继承体系赋予 Qt 类库高度的…...

在项目中调用本地Deepseek(接入本地Deepseek)

前言 之前发表的文章已经讲了如何本地部署Deepseek模型&#xff0c;并且如何给Deepseek模型投喂数据、搭建本地知识库&#xff0c;但大部分人不知道怎么应用&#xff0c;让自己的项目接入AI模型。 文末有彩蛋哦&#xff01;&#xff01;&#xff01; 要接入本地部署的deepsee…...

JAVA中常用类型

一、包装类 1.1 包装类简介 java是面向对象的语言&#xff0c;但是八大基本数据类型不符合面向对象的特征。因此为了弥补这种缺点&#xff0c;为这八中基本数据类型专门设计了八中符合面向面向对象的特征的类型&#xff0c;这八种具有面向对象特征的类型&#xff0c;就叫做包…...

PostgreSQL学习的必要性

据分析师、运维工程师&#xff0c;还是技术决策者&#xff0c;掌握 PostgreSQL 都能带来显著的优势。以下是其必要性的核心要点&#xff1a;企业级开源数据库的首选 功能全面性&#xff1a;PostgreSQL 支持复杂的 SQL 查询、事务&#xff08;ACID 特性&#xff09;、多版本并发…...

使用 GPTQ 进行 4 位 LLM 量化

权重量化方面的最新进展使我们能够在消费级硬件上运行大量大型语言模型&#xff0c;例如 RTX 3090 GPU 上的 LLaMA-30B 模型。这要归功于性能下降最小的新型 4 位量化技术&#xff0c;例如GPTQ、GGML和NF4。 在本文中&#xff0c;我们将探索流行的 GPTQ 算法&#xff0c;以了解…...

【黑马点评优化】2-Canel实现多级缓存(Redis+Caffeine)同步

【黑马点评优化】2-Canel实现多级缓存&#xff08;RedisCaffeine&#xff09;同步 0 背景1 配置MySQL1.1 开启MySQL的binlog功能1.1.1 找到mysql配置文件my.ini的位置1.1.2 开启binlog 1.2 创建canal用户 2 下载配置canal2.1 canal 1.1.5下载2.2 配置canal2.3 启动canal2.4 测试…...

【CUDA】Pytorch_Extensions

【CUDA】Pytorch_Extensions 为什么要开发CUDA扩展&#xff1f; 当我们在PyTorch中实现自定义算子时&#xff0c;通常有两种选择&#xff1a; 使用纯Python实现&#xff08;简单但效率低&#xff09;使用C/CUDA扩展&#xff08;高效但需要编译&#xff09; 对于计算密集型的…...

CPP集群聊天服务器开发实践(五):nginx负载均衡配置

1 负载均衡器的原理与功能 单台Chatserver可以容纳大约两万台客户端同时在线聊天&#xff0c;为了提升并发量最直观的办法需要水平扩展服务器的数量&#xff0c;三台服务器可以容纳六万左右的客户端。 负载均衡器的作用&#xff1a; 把client的请求按照负载均衡算法分发到具体…...

使用 NVM 随意切换 Node.js 版本

安装nvm https://github.com/coreybutler/nvm-windows/releases nvm安装详细教程&#xff08;卸载旧的nodejs&#xff0c;安装nvm、node、npm、cnpm、yarn及环境变量配置&#xff09;-CSDN博客 验证 NVM 是否安装成功-查看版本 nvm --version安装指定版本的 Node.js nvm i…...

百问网(100ask)的IMX6ULL开发板的以太网控制器(MAC)与物理层(PHY)芯片(LAN8720A)连接的原理图分析(包含各引脚说明以及工作原理)

前言 本博文承接博文 https://blog.csdn.net/wenhao_ir/article/details/145663029 。 本博文和博文 https://blog.csdn.net/wenhao_ir/article/details/145663029 的目录是找出百问网(100ask)的IMX6ULL开发板与NXP官方提供的公板MCIMX6ULL-EVK(imx6ull14x14evk)在以太网硬件…...

组件库地址

react&#xff1a; https://react-vant.3lang.dev/components/dialoghttps://react-vant.3lang.dev/components/dialog vue用v2的 Vant 2 - Mobile UI Components built on Vue...

2025.2.16机器学习笔记:TimeGan文献阅读

2025.2.9周报 一、文献阅读题目信息摘要Abstract创新点网络架构一、嵌入函数二、恢复函数三、序列生成器四、序列判别器损失函数 实验结论后续展望 一、文献阅读 题目信息 题目&#xff1a; Time-series Generative Adversarial Networks会议&#xff1a; Neural Information…...

最新智能优化算法: 中华穿山甲优化( Chinese Pangolin Optimizer ,CPO)算法求解23个经典函数测试集,MATLAB代码

中华穿山甲优化&#xff08; Chinese Pangolin Optimizer &#xff0c;CPO&#xff09;算法由GUO Zhiqing 等人提出&#xff0c;该算法的灵感来自中华穿山甲独特的狩猎行为&#xff0c;包括引诱和捕食行为。 算法流程如下&#xff1a; 1. 开始 设置算法参数和最大迭代次数&a…...

使用 DeepSeek + 语音转文字工具 实现会议整理

目录 简述 1. DeepSeek与常用的语音转文字工具 1.1 DeepSeek 1.2 讯飞听见 1.3 飞书妙记 1.4 剪映电脑版 1.5 Buzz 2. 安装Buzz 3. 使用DeepSeek Buzz提取并整理语音文字 3.1 使用 Buzz 完成语音转文字工作 3.2 使用 DeepSeek 进行文本处理工作 3.3 整理成思维导图…...

【OS安装与使用】part4-ubuntu22.04安装anaconda

文章目录 一、待解决问题1.1 问题描述1.2 解决方法 二、方法详述2.1 必要说明2.2 应用步骤2.2.1 官网下载Anaconda&#xff08;1&#xff09;确认自己的系统型号与硬件架构&#xff08;2&#xff09;官网下载对应版本 2.2.2 安装Anaconda&#xff08;1&#xff09;基于shell脚本…...

把程序加入开机自启动

一、Windows 系统 方法 1&#xff1a;通过启动文件夹 1. 按下 Win R&#xff0c;输入 shell:startup&#xff0c;回车打开 **启动文件夹**。 2. 将应用程序的快捷方式复制到此文件夹中。 右键应用程序主程序&#xff08;.exe&#xff09;→ 创建快捷方式 → 拖动到启动文件夹。…...

介绍cherrypick

git cherry-pick 是 Git 中的一个强大命令&#xff0c;用于将一个或多个提交&#xff08;commit&#xff09;从一个分支应用到另一个分支。它允许你选择性地将特定的变更引入到当前分支&#xff0c;而无需合并整个分支。以下是对 git cherry-pick 操作的详细介绍&#xff1a; 1…...

Spring IoC DI:控制反转与依赖注入

目录 前言 - Spring MVC 与 Spring IoC 之间的关系 1. IoC 1.1 Spring Framework, Spring MVC, Spring boot 之间的联系[面试题] 1.2 什么是容器 1.3 什么是 IoC 2. DI 2.1 什么是 DI 3. Spring IoC & DI 3.1 Component 3.2 Autowired 4. IoC 详解 4.1 Applica…...

JavaAPI常用类型(包装类、BigDecimal类)

包装类 java语言是面向对象的语言&#xff0c;但是其中的八大基本数据类型不符合面向对象的特征。 因此java为了弥补这样的缺点&#xff0c;为这八种基本数据类型专门设计了八种符合面向对象特征的的类型&#xff0c;这八种具有面向对象特征的类型&#xff0c;统称为包装类&a…...

项目中一些不理解的问题

1.Mybatis是干啥的 他是用来帮我们操作数据库的&#xff0c;相当于是我们的一个助手&#xff1a; 我们想要得到数据库中的什么数据&#xff0c;就可以告诉mybatis&#xff0c;他会给我们想要的结果&#xff0c;同时&#xff0c;我们想要对数据库做出什么操作&#xff0c;也可…...

数字化转型4化:标准化奠基-信息化加速-数字化赋能-智能化引领

​随着经济增速的放缓&#xff0c;大国体系所催生的生产力逐渐释放&#xff0c;后续业务的发展愈发需要精耕细作&#xff0c;精益理念也必须深入企业的骨髓。与此同时&#xff0c;在全球经济一体化的大背景下&#xff0c;企业面临着来自国内外同行&#xff0c;甚至是跨行业的激…...

Lineageos 22.1(Android 15) 开机向导制作

一、前言 开机向导原理其实就是将特定的category的Activity加入ComponentResolver&#xff0c;如下 <category android:name"android.intent.category.SETUP_WIZARD"/>然后我们开机启动的时候&#xff0c;FallbackHome结束&#xff0c;然后启动Launcher的时候…...

“让App玩捉迷藏:Android教育平板的‘隐身术’开发实录”

1. 前言&#xff1a;一场App的“消失魔术” 在定制教育平板时&#xff0c;客户要求&#xff1a;“朕要某些App在桌面上消失&#xff0c;只能在系统设置里当个‘幽灵’&#xff0c;而朕一声令下&#xff0c;它们又得原地复活&#xff01;”于是&#xff0c;程序员们翻开了Androi…...