目录
目标
常用API
工具方法
演示案例
allocate(int capacity)和allocateDirect(int capacity)
put()和get()
flip()和hasRemaining()
clear()
compact()
wrap()
总结
目标
掌握ByteBuffer常用方法,分析ByteBuffer对象在切换读写模式的情况下基本属性的变化情况。
常用API
| 方法 | 描述 | 案例 |
| allocate(int capacity) | 分配capacity个字节的缓冲区。返回HeapByteBuffer对象,即jdk内存堆字节缓冲区。 | ByteBuffer buffer = ByteBuffer.allocate(8); |
| allocateDirect(int capacity) | 分配capacity个字节的缓冲区。返回DirectByteBuffer对象,即直接内存字节缓冲区。 | ByteBuffer buffer = ByteBuffer.allocateDirect(8); |
| compact() | 将ByteBuffer切换到写入模式,从position处将缓冲区的字节移动到起始位置。 | buffer.compact(); |
| get() | 从ByteBuffer中读取1个字节,并将position向后移动1位。 | buffer.get(); |
| get(int index) | 根据index获取指定位置的字节,不会移动position。 | buffer.get(1); |
| put(byte[] src) | 向ByteBuffer写字节数组数据。 | buffer.put(new byte[]{'1','a'}); buffer.put("1a".getBytes()); |
| put(byte b) | 向ByteBuffer写字节数据。 | buffer.put((byte)127); |
| wrap(byte[] array) | 向ByteBuffer写字节数组数据。对缓冲区的修改将导致数组被修改,反之亦然。 新缓冲区的大小和limit为字节数组的长度。 | ByteBuffer.wrap("Hello World.".getBytes()); |
| flip() | 将ByteBuffer切换到读模式,position设置为0,limit设置为ByteBuffer内最后1个字节所在的索引数。 | buffer.flip(); |
| clear() | 将position设置为0,limit设置为capacity,mark被丢弃。 | buffer.clear(); |
| capacity() | 获取ByteBuffer的容量大小。 | buffer.capacity(); |
| hasRemaining() | position和limit之间是否有任何元素。 | buffer.hasRemaining(); |
工具方法
public void bufferDetails(ByteBuffer buffer) {System.out.print("position="+buffer.position());System.out.print(";limit="+buffer.limit());System.out.println(";capacity="+buffer.capacity());//读取数据不移动索引。for (int i = 0; i < buffer.limit(); i++) {System.out.print(buffer.get(i));System.out.print(" ");}System.out.println("\n");}
演示案例
allocate(int capacity)和allocateDirect(int capacity)
/*** JVM堆内存字节缓冲区* 直接内存字节缓冲区*/public void allocateTest(){ByteBuffer buffer = ByteBuffer.allocate(8);//是否是直接直接内存字节缓冲区System.out.println(buffer.isDirect());ByteBuffer buffer2 = ByteBuffer.allocateDirect(8);//是否是直接直接内存字节缓冲区System.out.println(buffer2.isDirect());}
put()和get()
/*** 从ByteBuffer中读取1个字节,并将position向后移动1位。*/public void getAndPutTest(){ByteBuffer buffer = ByteBuffer.allocateDirect(20);//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。buffer.put("Hello World !".getBytes());//切换到读模式buffer.flip();//position=0System.out.println(buffer.position());//输出72,ASCII表中H就是72System.out.println(buffer.get());//position=1System.out.println(buffer.position());//继续读取字节缓冲区返回position=1位置的数据,即返回e。System.out.println((char)buffer.get());}
flip()和hasRemaining()
/*** flip():将ByteBuffer切换到读模式,position设置为0,limit设置为ByteBuffer内最后1个字节所在的索引数。* hasRemaining() position和limit之间是否有任何元素。*/public void flipTest() {ByteBuffer buffer = ByteBuffer.allocateDirect(16);//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。buffer.put("123456789".getBytes());bufferDetails(buffer);//切换到读模式buffer.flip();bufferDetails(buffer);//读取数据并移动position。while(buffer.hasRemaining()){System.out.println(buffer.get());}//position=9。bufferDetails(buffer);}
打印结果

clear()
/*** clear():将position设置为0,limit设置为capacity,mark被丢弃。*/public void clearTest() {ByteBuffer buffer = ByteBuffer.allocateDirect(16);//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。buffer.put("123456789".getBytes());//切换到读模式buffer.flip();//读取数据并移动position。while(buffer.hasRemaining()){buffer.get();}//position=9。bufferDetails(buffer);//position=0;limit=16;capacity=16buffer.clear();bufferDetails(buffer);}
打印结果

compact()
/*** compact():将ByteBuffer切换到写入模式,从position处将缓冲区的字节移动到起始位置。*/public void compactTest(){ByteBuffer buffer = ByteBuffer.allocateDirect(16);//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。buffer.put("123456789".getBytes());//切换到读模式buffer.flip();//读取1个字节。此时的buffer为:position=1;limit=9;capacity=16buffer.get();buffer.compact();bufferDetails(buffer);//切换到读模式buffer.flip();//position=0;limit=8;capacity=16,由此打印证明最后一个9不会被重复读取。bufferDetails(buffer);}
打印结果

wrap()
/*** 向ByteBuffer写字节数组数据。对缓冲区的修改将导致数组被修改,反之亦然。* 新缓冲区的大小和limit为字节数组的长度。*/public void wrapTest(){byte[] bytes = "123456789".getBytes();ByteBuffer buffer = ByteBuffer.wrap(bytes);bufferDetails(buffer);buffer.get();buffer.compact();bufferDetails(buffer);//打印234567899,证明了我们对ByteBuffer操作影响了byte[]数组。System.out.println(new String(bytes));bytes[2]='a';//打印了50 51 97 53 54 55 56 57 57,证明了我们对byte[]数组操作影响了ByteBuffer。bufferDetails(buffer);}
打印结果

总结
区分读模式和写模式的标准在于limit属性,如果ByteBuffer存在剩余空间,则:
- limit=capacity表示当前为写模式;
- limit=数据量表示当前模式为读模式。













