news 2026/5/16 16:50:43

《Java 100 天进阶之路》第23篇:缓冲区数据结构 ByteBuffer

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《Java 100 天进阶之路》第23篇:缓冲区数据结构 ByteBuffer

第23篇:缓冲区数据结构 ByteBuffer


📌系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第22篇:Java字符串简介 |
➡️ 下一篇:第24篇:Java枚举类型 enum 用法👈待发布


一、核心知识点

  • Buffer 抽象类与子类(ByteBufferCharBufferIntBuffer等)
  • ByteBuffer核心属性:capacitylimitpositionmark
  • 核心方法:put()get()flip()rewind()clear()compact()
  • 直接缓冲区 vs 堆缓冲区
  • NIO(New I/O)中的使用场景

二、通俗讲解(1分钟开心学)

1. 什么是 Buffer?

Buffer是 Java NIO 中用于存储数据的容器,可以理解为一块可以读写的内存区域,并带有一套指针系统来管理读写位置。最常用的是ByteBuffer

2. 四个核心属性

  • capacity:容量,创建后不可变。
  • limit:读写的极限位置。
  • position:下一个要读/写的位置索引。
  • mark:标记位置,可用reset()返回。

3. 两种模式

  • 写模式:刚创建时,position = 0limit = capacity,往里面put数据。
  • 读模式:调用flip()后,limit = position(原写到的位置),position = 0,然后get数据。

生活类比
缓冲区就像一个水池。capacity是水池总容量。你在水池里倒水(写),position是水面高度。倒完后,你标记一下现在的水位(flip),然后开始从底部取水(读)。取水时不能超过之前的水位(limit)。

4. 直接缓冲区 vs 堆缓冲区

  • 堆缓冲区allocate()):内存分配在 JVM 堆上,受 GC 管理,数据拷贝到 native 内存时多一次复制。
  • 直接缓冲区allocateDirect()):内存分配在系统本机内存(native heap),减少一次拷贝,适合大文件、网络传输,但分配和释放成本高。

三、实操代码案例 + 场景说明

场景:使用ByteBuffer实现一个简单的“写数据 → 读数据”流程。

importjava.nio.ByteBuffer;importjava.nio.charset.StandardCharsets;publicclassByteBufferDemo{publicstaticvoidmain(String[]args){// 1. 创建堆缓冲区,容量10ByteBufferbuffer=ByteBuffer.allocate(10);System.out.println("初始: pos="+buffer.position()+", limit="+buffer.limit());// 2. 写入数据buffer.put((byte)'H');buffer.put((byte)'i');buffer.put((byte)'!');System.out.println("写入后: pos="+buffer.position());// 3// 3. 切换到读模式buffer.flip();System.out.println("flip后: pos="+buffer.position()+", limit="+buffer.limit());// pos=0, limit=3// 4. 读取数据while(buffer.hasRemaining()){System.out.print((char)buffer.get());}System.out.println();// 输出 "Hi!"// 5. rewind:重新读buffer.rewind();System.out.println("rewind后 pos="+buffer.position());// 0// 6. clear:清空状态,准备重新写buffer.clear();System.out.println("clear后 pos="+buffer.position()+", limit="+buffer.limit());// pos=0, limit=10// 7. 直接缓冲区示例ByteBufferdirectBuf=ByteBuffer.allocateDirect(1024);if(directBuf.isDirect()){System.out.println("这是直接缓冲区,适合网络传输");}// 8. 字符串与 ByteBuffer 互转Stringmsg="Hello NIO";ByteBufferbuf=ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));// 读取时byte[]bytes=newbyte[buf.remaining()];buf.get(bytes);Stringdecoded=newString(bytes,StandardCharsets.UTF_8);System.out.println(decoded);}}

四、避坑要点

错误/误区后果正确做法
写入后忘记flip()直接读取读不到数据(position 在末尾)写后读前必须flip()
flip()多次调用limit被错误设置只在切换模式时调用一次
直接缓冲区频繁分配释放性能反而下降复用缓冲区或使用池化技术
使用get()前不判断hasRemaining()可能抛出BufferUnderflowException先判断或捕获异常

五、面试高频考点

Q1:ByteBufferflip()方法做了什么?

limit设为当前positionposition归零,为从写模式切换到读模式做准备。

Q2:直接缓冲区的优缺点?

优点:减少 JVM 堆和 native 堆之间的数据拷贝,提高 I/O 性能,适合大文件、网络。缺点:分配和释放成本高,不受 JVM 堆大小限制但受物理内存限制。

Q3:clear()compact()的区别?

clear()重置position=0, limit=capacity,丢弃未读数据;compact()将未读数据复制到缓冲区头部,position移到未读数据后,limit=capacity,为写入留出空间。

六、练习题

  1. 代码填空:完成如下操作:写入字符串 “Java” 的字节,然后读取并打印。
  2. 简答:什么时候使用直接缓冲区?什么时候使用堆缓冲区?
  3. 动手:用ByteBufferFileChannel实现文件拷贝(使用transferToread/write)。

📊 你的学习进度

  • 当前:第23篇 / 共44篇 ·第三阶段:字符串、Buffer、枚举、类加载(第21~25篇)
  • ✅ 已完成:第1~22篇
  • 📖 正在学:第23篇
  • ⏳ 待学习:第24~44篇

👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇

💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!


下一篇文章预告

《Java枚举类型 enum 用法》

内容简介:枚举的定义、构造器、成员变量和方法,values()/valueOf()/ordinal(),枚举单例模式。

💡 学完这篇,你将掌握枚举的全部用法,并用枚举写出更安全的代码。

📌《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/16 16:50:22

为什么 AI 不会变得有意识:从拟人映射到生命性意识的边界

自现代科学诞生以来,人类不断幻想创造一个“人工版本的自己”:从文学中的人造生命,到电影中的会思考机器,再到今天的大型语言模型和具身智能系统,这个梦想随着每一轮技术浪潮被重新点燃。今天的 AI 已经在许多方面表现…

作者头像 李华
网站建设 2026/5/16 16:45:03

从零到一:用Python实现MTCNN人脸检测的实战指南

1. 初识MTCNN:为什么选择这个算法? 第一次接触人脸检测时,我被各种算法搞得眼花缭乱。试过Haar特征,也玩过HOGSVM,直到遇到MTCNN才发现这才是真正实用的解决方案。这个由Kaipeng Zhang等人在2016年提出的算法&#xff…

作者头像 李华
网站建设 2026/5/16 16:40:33

从Gmsh几何建模到Meshlab后处理:一个完整CFD前处理工作流分享

从Gmsh几何建模到Meshlab后处理:CFD前处理全流程实战指南 在计算流体力学(CFD)和有限元分析领域,高质量的网格生成往往是仿真成功的关键前提。许多工程师都经历过这样的困境:在Gmsh中精心设计的几何模型,经…

作者头像 李华
网站建设 2026/5/16 16:40:10

Node.js 服务如何集成 Taotoken 实现统一的多模型 API 调用与管理

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Node.js 服务如何集成 Taotoken 实现统一的多模型 API 调用与管理 对于需要在前端或服务端动态调用不同大语言模型的 Node.js 项目…

作者头像 李华