先列点代码片段:
// ...
//
// 此段代码功能为从 t.txt 里复制所有数据到 out_j.txt:
//
...
1 FileChannel fcin = new FileInputStream( "d:/t.txt" ).getChannel();
2 FileChannel fcout = new FileOutputStream( new File( "d:/out_j.txt" )).getChannel();
3 ByteBuffer buff = ByteBuffer.allocate( 1024 );
4 long t1 = System.currentTimeMillis();
5
6 while( fcin.read( buff ) != -1 )
7 {
8   buff.flip();
9   fcout.write( buff );
10   buff.clear();
11 }
12
13 long t2 = System.currentTimeMillis();
14 long size = fcin.size();
15 javax.swing.JOptionPane.showMessageDialog( null, size + " 字节, 耗时 " + ( t2 - t1 + 1 ) + " ms." );
...

----------------------------------------------------------------------------------------------------

SDK 文档里对 ByteBuffer 的说明为:

public abstract class ByteBuffer
extends Buffer
implements Comparable <ByteBuffer>

这说明 ByteBuffer 是继承于 Buffer 的抽象类, 实现了两个接口.

行3 通过 allocate() 分配了一块 1024 字节的缓冲区, 并返回一个 ByteBuffer 对象. (抽象类不能直接 new)
行6 fcin.read() 将数据读入到 buff. 此处的 read() 是 FileChannel 类的一个虚函数.
行8 buff.flip() 这个调用就是开头一直无法理解的部分.

----------------------------------------------------------------------------------------------------

SDK 文档里的对 flip() 的说明是:

public final Buffer flip()
反转此缓冲区。首先对当前位置设置限制,然后将该位置设置为零。如果已定义了标记,则丢弃该标记。
当将数据从一个地方传输到另一个地方时,经常将此方法与 compact 方法一起使用。

我最终的理解是: 文档翻译得太差了, 把不应该翻译的内容也译成了中文, 所以反而不容易理解.
关键就在以下 2 处:

当前位置: 这个可以直观地理解为缓冲区中的当前数据指针, 或是 SQL 中的游标, 记为 curPointer.
限制: 这个可以理解成实际操作的缓冲区段的结束标记, 记为 endPointer.
反转: 这个完全是对 flip 这个词不负责的翻译, 如果参照 DirectX 里的 flip() 而译为翻转/翻页, 那就好理解得多, 就像写信/看信, 写/看完一页后, 翻到下一页, 眼睛/笔从页底重新移回页首.
这个翻转背后的操作其实就是 "把 endPointer 定位到 curPointer 处, 并把 curPointer 设为 0".

关于标记, 在这里不涉及. 下一句说到常与 compact 方法一起使用, 是可以想像的, 因为 compact 方法对数据进
行了压缩, 有效数据的真实长度发生了变化, 肯定需要用 flip 重新定位结束标记.

在填充, 压缩等数据操作时, curPointer 估计都是自动更新了位置的, 总是指向最后一个有效数据, 所以每次调
用 flip() 后, endPointer 就指向了有效数据的结尾, 而 curPointer 指向了 0 (缓冲起始处).

举个图例:
(c 和 e 分别代表 curPointer 和 endPointer 两个指针)

* 先是一个空的 ByteBuffer (大小为 10 字节)
-------------------
-------------------
c
e

* 然后填充 5 字节数据
-------------------
0 1 2 3 4
-------------------
e          c
此时, endPointer 尚在 0 处, curPointer 移到了数据结尾.
经测试, 此时若取数据, 将得到 5 个字节, 内容通常为 0 (也有可能是未知), 因为实际上取到的是从 c 处到缓冲
区实际结束处的 5 个未初始化的字节.

* 调用一次 flip() 后
-------------------
0 1 2 3 4
-------------------
c          e
此时, endPointer 先被移到 curPointer, 然后 curPointer 移到 0.
通过测试可见, ByteBuffer 取数据时, 是从 curPointer 起, 到 endPointer 止, 若 curPointer > endPointer, 则取到缓冲区结束.

再看上面代码的关键片段, 行 8 处调用 flip() 即有两个作用, 一是将 curPointer 移到 0, 二是将 endPointer 移到有效数据结尾.

此行可由以下两行代替:
buff.limit( buff.position());
buff.position( 0 );

可见对其工作原理的理解, 应该是正确的.

----------------------------------------------------------------------------------------------------

总结如下:
1. put 数据时, 不会自动清除缓冲区中现有的数据.
2. 每一次 get 或 put 后, curPointer 都将向缓冲区尾部移动, 移动量=操作的数据量.
3. get/put 均是从 curPointer 起, 到 curPointer + 操作的数据长度止.
4. get/put 操作中, 若 curPointer 超过了 endPointer 或缓冲区总长度, 将抛出 java.nio.BufferUnderflowException 异常.

注: curPointer 和 endPointer 只是为文中方便描述命名的, 实际分别对应到 ByteBuffer.position() 和 ByteBuffer.limit() 两个方法.

java ByteBuffer flip()和limit()的理解相关推荐

  1. Java ByteBuffer –速成课程

    以我的经验,当开发人员第一次遇到java.nio.ByteBuffer时,会引起混乱和细微的错误,因为如何正确使用它尚不明显. 在我对API文档感到满意之前,需要反复阅读API文档和一些经验以实现一些 ...

  2. Java ByteBuffer用法

    ByteBuffer的常用属性 1.position 标识下一个byte的操作位 2.limit 标识上界 3.capacity 标识容量 4.mark 辅助标识 ByteBuffer的常用函数 By ...

  3. java bytebuffer 大小,bytebuffer 获取长度

    练习题4 ? 问题:对于以下代码: int n=(byteBuffer); //假定n>=0 (); 假定执行(byteBuffer)方法前,byteBuffer的 容量.极限和位置分别为c.l ...

  4. java bytebuffer 清空_Java ByteBuffer用法总结

    最近用SocketChannel进行网络编程比较多,中间也遇到了几个问题,出现的bug也主要来自于对于ByteBuffer的使用不当.现在终于调通了,对ByteBuffer及Socket网络编程也有了 ...

  5. java局部变量全局变量,实例变量的理解

    java局部变量全局变量,实例变量的理解 局部变量 可以理解为写在方法中的变量. public class Variable {//类变量static String name = "小明&q ...

  6. 阿里JAVA开发手册零度的思考理解(二)

    转载请注明原创出处,谢谢! 说在前面 人生的大道上默默地走,就必须要有一盏灯亮着为你引导方向!而这盏灯抑或只是一句话,一句鼓励,一个赞美,一次承认,一次认可,一次相识一次交流-- 上篇文章:阿里JAV ...

  7. java static关键字_好程序员Java教程分享static关键字的理解

    好程序员Java教程分享static关键字的理解,static关键字含义可以理解为静态的. 1. 当其修饰属性时,该属性为整个类公有,所有的对象操作的都是同一个静态属性.所以调用时应该使用类名去调用, ...

  8. Java受查异常和运行时异常的理解

    Java受查异常和运行时异常的理解 概念与理解 怎么处理 概念与理解 Java提供三种可抛出结构(throwable):受查异常(checked exception),运行时异常(runtime ex ...

  9. Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构

    Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构 概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留 ...

最新文章

  1. 为什么校招面试中总被问“线程与进程的区别”?我该如何回答?
  2. 市场份额一般是多少_一瓶500毫升的啤酒相当于多少白酒?
  3. LiveVideoStackCon 音视频技术大会 2022 上海站日程发布啦!
  4. 数论四之综合训练——Magic Pairs,Crime Management,Top Secret,组合数问题
  5. 联邦学习安全与隐私保护综述 A survey on security and privacy of federated learning
  6. 鹤岗一中2021年高考成绩查询,2021鹤岗市地区高考成绩排名查询,鹤岗市高考各高中成绩喜报榜单...
  7. 漂亮、免费和响应式HTML5网站模板 - 转
  8. itertools chain
  9. JavaScript:数组、函数和对象
  10. Teigha 4.0 Net 开发记录
  11. 2022.3.14 阿里笔试
  12. 黄渤海浅层气的分布及特征综述
  13. My Sunshine
  14. 依据Right-BICEP要求的对四则运算2的测试
  15. 最强赛亚人服务器维护,最强赛亚人官方,最强赛亚人手游官方正版预约 v1.1.0-手游汇...
  16. 商家开通直播前需了解哪些市场数据?
  17. 2023年全国最新机动车签字授权人精选真题及答案10
  18. 约约约,文章约起来!
  19. php 画布插入图像,PHP图片处理之图片背景、画布操作
  20. Qemu 调试内核 出错 Remote 'g' packet reply is too long:

热门文章

  1. jQuery实现百度导航li拖放排列效果,即时更新数据库
  2. 用迭代法求方程cos(y)-y=0的一个实根
  3. python储存数据分行_基于python实现对文件进行切分行
  4. 大数据可视化技术的作用有哪些
  5. 物联网云平台有哪些优势
  6. python公开课乐博学院_乐搏学院VIP36期全栈班学习群 - 乐搏软件教育 - 软件测试 - Powered By EduSoho...
  7. mysql对应systables_mysql5.7中的sys表详解(转)
  8. eclipse不报错 intelliji 报错_小白提问:导入内置包winsound不报错但没声音是什么情况?...
  9. java scanner以回车结束_大佬看了直呼内行,你当初Java刚入门是否也是这样写代码?...
  10. mysql 表迁移 并筛选_使用perl实现拆分数据表(mysql)并迁移数据实例