首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java闭包是什么?5分钟让你搞明白

Java闭包是什么?5分钟让你搞明白

原创
作者头像
Eulogy
发布2025-07-07 21:19:47
发布2025-07-07 21:19:47
1650
举报
文章被收录于专栏:笔记本笔记本

Java闭包是什么?5分钟让你搞明白

先说说函数式接口

在讲闭包之前,我们先了解一下函数式接口。你可能已经见过这样的代码:

代码语言:java
复制
// 传统写法:创建一个接口的实现
Runnable task = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello World");
    }
};

这里的Runnable就是一个函数式接口,它的特点是:只有一个抽象方法需要实现

Java中有很多这样的函数式接口:

  • Runnable接口只有一个run()方法
  • Function<T,R>接口只有一个apply()方法
  • Consumer<T>接口只有一个accept()方法

既然函数式接口只有一个方法,Java 8就提供了Lambda表达式来简化写法:

代码语言:java
复制
// 传统写法
Function<Integer, Integer> 加1 = new Function<Integer, Integer>() {
    @Override
    public Integer apply(Integer x) {
        return x + 1;
    }
};

// Lambda简化写法
Function<Integer, Integer> 加1简化版 = x -> x + 1;

看到了吗?Lambda表达式x -> x + 1其实就是在实现Function接口的apply方法。

什么是闭包?

闭包听起来很高大上,其实就是一个简单的概念:函数能够"记住"并使用它外面的变量

就像你在家里(函数)能够使用客厅里的电视(外部变量)一样,即使你后来搬到了别的地方,你依然记得那台电视。

用大白话解释

代码语言:java
复制
import java.util.function.Function;

public class 简单闭包例子 {
    public static void main(String[] args) {
        int 外面的数字 = 10;
        
        // 这个Lambda表达式实际上是在实现Function接口
        // 但它"记住"了外面的数字 - 这就是闭包!
        Function<Integer, Integer> 乘法器 = x -> x * 外面的数字;
        
        System.out.println(乘法器.apply(5)); // 输出: 50
    }
}

看到了吗?乘法器这个Lambda表达式实际上是在实现Function接口,但它神奇的地方在于:它能使用外面的外面的数字变量。这就是闭包!

换句话说,闭包就是:Lambda表达式 + 它能访问的外部变量

真实的例子

例子1:做个计算器

代码语言:java
复制
import java.util.function.Function;

public class 计算器例子 {
    // 这个方法返回一个"专门乘某个数"的函数
    public static Function<Integer, Integer> 做个乘法器(int 倍数) {
        return 数字 -> 数字 * 倍数; // 闭包:记住了"倍数"
    }
    
    public static void main(String[] args) {
        // 做一个专门乘2的函数
        Function<Integer, Integer> 乘以2 = 做个乘法器(2);
        
        // 做一个专门乘10的函数  
        Function<Integer, Integer> 乘以10 = 做个乘法器(10);
        
        System.out.println(乘以2.apply(5));  // 输出: 10
        System.out.println(乘以10.apply(5)); // 输出: 50
    }
}

例子2:过滤数据

代码语言:java
复制
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class 过滤例子 {
    public static void main(String[] args) {
        List<Integer> 数字们 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        
        int 标准 = 5;
        
        // 闭包:记住了"标准"这个变量
        List<Integer> 大数字们 = 数字们.stream()
            .filter(数字 -> 数字 > 标准)  // 这里用了外面的"标准"
            .collect(Collectors.toList());
        
        System.out.println(大数字们); // 输出: [6, 7, 8, 9, 10]
    }
}

有个小限制

Java的闭包有个规定:被"记住"的变量不能改变

代码语言:java
复制
public class 限制例子 {
    public static void main(String[] args) {
        int 计数器 = 0;
        
        // 这样写会报错,因为试图改变"计数器"
        // Runnable 任务 = () -> 计数器++; // 编译错误!
        
        // 正确的做法:用个盒子装着
        AtomicInteger 计数器盒子 = new AtomicInteger(0);
        Runnable 任务 = () -> {
            int 新值 = 计数器盒子.incrementAndGet();
            System.out.println("计数: " + 新值);
        };
        
        任务.run(); // 输出: 计数: 1
        任务.run(); // 输出: 计数: 2
    }
}

实际中怎么用?

按钮点击处理

代码语言:java
复制
JButton 按钮 = new JButton("点我");
String 消息 = "你点击了按钮!";

// 闭包:记住了"消息"
按钮.addActionListener(事件 -> {
    JOptionPane.showMessageDialog(null, 消息);
});

数据处理

代码语言:java
复制
List<String> 名字们 = Arrays.asList("小明", "小红", "小刚");
String 前缀 = "同学";

// 闭包:记住了"前缀"
List<String> 称呼们 = 名字们.stream()
    .map(名字 -> 前缀 + 名字)
    .collect(Collectors.toList());

System.out.println(称呼们); // 输出: [同学小明, 同学小红, 同学小刚]

总结

闭包就是这么简单:

  • 函数能记住外面的变量
  • 像做了个快照一样,保存了当时的环境
  • Java用Lambda表达式来实现闭包
  • 被记住的变量不能改变(或者用特殊的盒子装着)

下次看到Lambda表达式用了外面的变量,你就知道了:哦,这就是闭包!

没那么复杂,对吧?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java闭包是什么?5分钟让你搞明白
    • 先说说函数式接口
    • 什么是闭包?
    • 用大白话解释
    • 真实的例子
      • 例子1:做个计算器
      • 例子2:过滤数据
    • 有个小限制
    • 实际中怎么用?
      • 按钮点击处理
      • 数据处理
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档