Lambda作用域

背景

函数式方法

复制代码
    /**
     * 生成Excel文件并在使用后自动清理
     * @param data 数据列表
     * @param clazz 数据类型Class
     * @param fileName 文件名
     * @param sheetName sheet名称
     * @param sheetNo sheet编号
     * @param function 文件处理函数
     */
    public static <T, R> R generateAndProcessExcelFile(List<T> data,
                                                       Class<T> clazz,
                                                       String fileName,
                                                       String sheetName,
                                                       Integer sheetNo,
                                                       Function<Path, R> function) {
        Path path = null;
        try {
            path = generateExcelFile(data, clazz, fileName, sheetName, sheetNo, null);
            return function.apply(path);
        } finally {
            // 自动清理临时文件
            if (path != null) {
                try {
                    Files.deleteIfExists(path);
                } catch (Exception e) {
                    log.warn("自动删除临时文件失败: {}", path, e);
                }
            }
        }
    }

调用该工具类方法代码

复制代码
	public static <T> String writeMsg2Excel(String fileName,
											List<T> dtoList,
											Class<T> clazz,
											int sheetNo,
											String sheetName,
											long expireTime,
											TimeUnit unit) {
		long expireSecondLong = unit.toSeconds(expireTime);
		Integer expireSecond = (int) expireSecondLong;
		FileClient fileClient = SpringUtil.getNonnullBean(FileClient.class);
		FileUploadDTO fileUploadDTO =
				// fileName被lambada方法调用,不能在外面添加后缀
				FileUtil.generateAndProcessExcelFile(dtoList, clazz, fileName + ExcelTypeEnum.XLSX.getValue(), sheetName, sheetNo,
						path -> {
							// 这里对文件过期时间没有专门设置,默认2099,方法属于通用方法,不敢加过期时间
							FileUploadParam fileUploadParam =
									FileUploadParam.simpleBuild(path.toFile(), expireSecond, com.test.file.common.FileLevelEnum.S3);
							fileUploadParam.setFileName(fileName + ExcelTypeEnum.XLSX.getValue());
							fileUploadParam.getDownUrlParam().setDownloadName(fileName + ExcelTypeEnum.XLSX.getValue());
							return fileClient.uploadFile(fileUploadParam);
						});
		return fileUploadDTO.getFileUrl();
	}

为什么expireSecond没有作为入参给到函数式接口,却可以在lambda中正常使用?

Lambda 表达式可以访问其外部作用域中的:

  • 局部变量(必须是 effectively final)
  • 实例变量
  • 静态变量

expireSecond 属于第一种情况,虽然它并没有标记final

  • expireSecond 是在 Lambda 表达式外部定义的局部变量
  • 它在 Lambda 表达式内部被引用时,Java 会自动捕获这个变量
  • 由于 expireSecond 在之后没有被重新赋值,它被视为"实际上的最终变量"(effectively final)

如果expireSecond在方法中有赋值操作,整个方法会报错。

编译器是如何处理的

编译器会在内部将 expireSecond 包装成 Lambda 表达式的上下文

expireSecond也可以作为入参传入

复制代码
    /**
     * 生成并处理Excel文件
     * <p>
     * 该方法首先根据提供的数据生成Excel文件,然后使用指定的函数对接生成的文件进行处理,
     * 处理完成后会自动清理生成的临时文件。
     *
     * @param <T>          数据类型
     * @param <R>          返回值类型
     * @param data         要写入Excel的数据列表
     * @param clazz        数据对象的Class类型,用于反射获取字段信息
     * @param fileName     Excel文件名
     * @param sheetName    Excel工作表名称
     * @param expireSecond 过期时间(秒),用于文件处理时的时间限制
     * @param function     处理Excel文件的函数,接收文件路径和过期时间作为参数
     * @return 处理结果
     */
    public static <T, R> R generateAndProcessExcelFile(List<T> data,
                                                       Class<T> clazz,
                                                       String fileName,
                                                       String sheetName,
                                                       Integer expireSecond,
                                                       BiFunction<Path, Integer, R> function) {
        Path path = null;
        try {
            path = generateExcelFile(data, clazz, fileName, sheetName, null);
            return function.apply(path, expireSecond);
        } finally {
            // 自动清理临时文件
            if (path != null) {
                try {
                    Files.deleteIfExists(path);
                } catch (Exception e) {
                    log.warn("自动删除临时文件失败: {}", path, e);
                }
            }
        }
    }
相关推荐
小杍随笔3 分钟前
Rust桌面GUI框架:性能优化与实战避坑指南
开发语言·性能优化·rust
二哈赛车手6 分钟前
新人笔记---项目中简易版的RAG检索后评测指标(@Recall ,Mrr..)实现
java·开发语言·笔记·spring·ai
做时间的朋友。7 分钟前
精准核酸检测
java·数据结构·算法
格林威8 分钟前
3D相机视觉检测:环境光太强,结构光点云全是噪点怎么办?
开发语言·人工智能·数码相机·计算机视觉·3d·视觉检测·工业相机
Rust语言中文社区15 分钟前
【Rust日报】2026-05-02 Temper - 用 Rust 编写的 Minecraft 服务器项目发布 0.1.0 版
运维·服务器·开发语言·后端·rust
许彰午19 分钟前
CacheSQL(五):桥接篇
java·数据库·缓存·系统架构
ATCH IERV30 分钟前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot
咸鱼2.01 小时前
【java入门到放弃】XXL-JOB
java
爱滑雪的码农1 小时前
Java基础十一 流(Stream)、文件(File)和IO
java·开发语言·python
叶小鸡1 小时前
Java 篇-项目实战-天机学堂(从0到1)-day11
java·开发语言