一文搞懂「回调」:从前端箭头函数到 Java Lambda 与线程模型
一文搞懂「回调」:从前端箭头函数到 Java Lambda 与线程模型
很多初学者(甚至工作一两年的人)都会卡在几个问题上:
- 什么是回调?
- 为什么前端到处是
() => {} - Java 的
() -> {}(Lambda)到底在干嘛 Runnable是什么?为什么线程start()里看不到run()- 排序、遍历为什么也要传函数?
这些问题表面看是语法差异,本质其实是同一个思想。
这篇文章,我试着用一条主线把它们全部串起来。
一、先给结论:什么是回调?
回调 = 把“将来要执行的代码”,先交给别人,让别人合适的时候再来调用你
关键词只有一个:不是你现在调用,是别人之后调用。
二、最生活化的理解(非常重要)
想象你点外卖,对骑手说一句话:
“到了给我打电话”
你做了三件事:
- 把事交给了别人(骑手)
- 告诉他 到时候要干什么
- 你自己不用等、也不用管
📌
这个“到了给我打电话”,本质就是回调。
三、前端:为什么 () => {} 到处都是回调?
1️⃣ 点击事件(最典型)
button.onclick = () => {
console.log("我被点了");
};
这里发生了什么?
- 你没有调用这个函数
- 你只是把它交给浏览器
- 将来用户点击时,浏览器来调用你
👉 这是 100% 的回调
2️⃣ 定时器
setTimeout(() => {
console.log("3 秒后执行");
}, 3000);
人话翻译:
“你帮我计时,时间到了再执行我给你的代码”
你不知道 3 秒什么时候结束,
所以只能用回调告诉它结束后怎么办。
3️⃣ 数组遍历 / 排序(容易被忽略)
[3, 1, 2].sort((a, b) => a - b);
你其实是在对数组说:
“我不管你怎么排
两个数谁在前,你用这段规则来判断”
📌
这个 (a, b) => a - b,不是你在调用,
是 sort 内部在反复调用 —— 所以它也是回调。
四、JS 箭头函数 () => {} 本身是不是回调?
不是。
() => {}只是一个“函数写法”
当它被“当参数传出去,将来再执行”时,才叫回调。
对比一下就清楚了:
// 普通函数调用(不是回调)
const f = () => console.log("hi");
f();
// 回调
setTimeout(() => console.log("hi"), 1000);
👉 区别只在一句话:谁来调用?什么时候调用?
五、Java:Lambda () -> {} 是什么?
Java 的 Lambda,本质和 JS 箭头函数是一样的:
把一段可执行逻辑,当成一个值传来传去
对照一下你就明白了
| JS | Java |
|---|---|
() => {} | () -> {} |
| 回调函数 | Lambda |
| 浏览器/事件循环调用 | 线程/框架调用 |
六、Runnable 是什么?为什么线程要它?
先看 Runnable 的真身:
public interface Runnable {
void run();
}
就这一行。
用一句大白话解释:
Runnable = 一份“任务说明书”
上面只写一件事:run() 里要干什么
它 不执行,
它只是描述“要执行的逻辑”。
七、线程为什么是 start(),而不是 run()?
这是很多人第一次看源码时的巨大疑惑。
你甚至已经发现了这一点:
Thread.start() 的源码里根本没调用 run()。
原因只有一句话:
run() 必须在“新线程”里执行,而 start() 是在“当前线程”里被调用的
真正的执行链路是:
main 线程
↓
Thread.start()
↓
native start0() (JVM / OS 创建新线程)
↓
新线程入口
↓
Thread.run()
↓
Runnable.run()
📌
run() 是 新线程启动后,被 JVM 回调执行的。
八、为什么说“线程模型本身就是回调模型”?
你写的代码是这样的:
new Thread(() -> {
System.out.println("do work");
}).start();
你实际上是在对 JVM 说:
“线程什么时候真正跑起来,我不管
跑起来以后,请执行我给你的这段代码”
这和前端的:
setTimeout(() => {}, 1000);
思想一模一样。
九、排序、遍历、线程:为什么都要用回调?
因为它们有一个共同点:
控制权不在你手里
- 排序:算法在库里
- 遍历:循环在框架里
- 线程:执行时机在 JVM / OS
- 点击:事件在浏览器
你只能告诉它一句话:
“到你合适的时候,用这段逻辑处理”
👉 这就是回调存在的根本原因。
十、一句话把整篇文章串起来
回调不是“高级技巧”,而是一种“控制权转移”的编程方式
- 你不决定“什么时候执行”
- 你只提供“怎么执行”
- 真正执行的那一刻,由别人来回头调用你
十一、你现在如果能说出这几句话,说明真的懂了
() => {}/() -> {}只是函数写法- 被传出去、将来被别人调用 → 才叫回调
- Runnable 不是线程,是线程要执行的内容
start()不直接调用run(),是 JVM 在新线程里回调它- 排序、遍历、线程、事件,本质都是同一套思想
更多推荐



所有评论(0)