1.put()与get()
/*
ByteBuffer类型化的 get() 与 put()
byteBuffer可以存不同的类型,但是取的时候得按顺序取(字节码会自动识别),但如果循环取,会取错值
*/
public static void main(String[] args) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(64);
buffer.putInt(15);
buffer.putLong(60000000L);
buffer.putDouble(15.666);
buffer.putChar('学');
buffer.putShort((short) 2);
buffer.putChar('习');
buffer.flip();
System.out.println(buffer.getInt());
System.out.println(buffer.getLong());
System.out.println(buffer.getDouble());
System.out.println(buffer.getChar());
System.out.println(buffer.getShort());
System.out.println(buffer.getChar());
}
2.slice()
/**
* Creates a new byte buffer whose content is a shared subsequence of
* this buffer's content.
*
* <p> The content of the new buffer will start at this buffer's current
* position. Changes to this buffer's content will be visible in the new
* buffer, and vice versa(反之亦然); the two buffers' position, limit, and mark
* values will be independent(独立的).
*
* <p> The new buffer's position will be zero, its capacity and its limit
* will be the number of bytes remaining in this buffer, and its mark
* will be undefined. The new buffer will be direct if, and only if, this
* buffer is direct, and it will be read-only if, and only if, this buffer
* is read-only. </p>
*
* @return The new byte buffer
*/
public abstract ByteBuffer slice();
public class NioTest {
/**
* Slice Buffer,与原有 buffer 共享相同的数组
*/
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(10);
for (int i = 0; i < buffer.capacity(); i++) {
buffer.put((byte)i);
}
buffer.position(2);
buffer.limit(6);
ByteBuffer slice = buffer.slice();
System.out.println(slice);//java.nio.HeapByteBuffer[pos=0 lim=4 cap=4]
for (int i = 0; i < slice.capacity(); i++) {
byte b = slice.get(i);
b += 100;
slice.put(i, b);
}
buffer.position(0);
buffer.limit(buffer.capacity());
while (buffer.hasRemaining()) {
System.out.print(buffer.get() + ", ");
}
}
}
输出:
java.nio.HeapByteBuffer[pos=0 lim=4 cap=4]
0, 1, 102, 103, 104, 105, 6, 7, 8, 9,
3.asReadOnlyBuffer()
/**
* Creates a new, read-only byte buffer that shares this buffer's
* content.
*
* <p> The content of the new buffer will be that of this buffer. Changes
* to this buffer's content will be visible in the new buffer(改变原来的buffer影响新Buffer);
* the new buffer itself, however, will be read-only and will not allow the shared
* content to be modified(新buffer只可以读,不可以修改). The two buffers' position, limit,
* and mark values will be independent(独立的).
*
* <p> The new buffer's capacity, limit, position, and mark values will be
* identical to those of this buffer(初始值是和原来的buffer相同的).
*
* <p> If this buffer is itself read-only then this method behaves in
* exactly the same way as the {@link #duplicate duplicate} method. </p>
*
* @return The new, read-only byte buffer
*/
public abstract ByteBuffer asReadOnlyBuffer();
/**
* 只读Buffer,我们随时可以将一个普通buffer调用asReadOnlyBuffer()返回一个只读Buffer
* 但不能将一个只读Buffer转换为读写Buffer
* 只读缓存底层是:HeapByteBufferR,而普通缓冲底层是:HeapByteBuffer。
*/
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(10);
System.out.println(buffer.getClass());
for (int i = 0; i < buffer.capacity(); i++) {
buffer.put((byte)i);
}
ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();
System.out.println(readOnlyBuffer.getClass());
System.out.println(readOnlyBuffer);
readOnlyBuffer.position(0);
//readOnlyBuffer.put((byte) 3);
}
class java.nio.HeapByteBuffer
class java.nio.HeapByteBufferR
java.nio.HeapByteBufferR[pos=10 lim=10 cap=10]//初始值为原来buffer的值
是怎么实现只读的呢?查看源码便知:
public ByteBuffer put(byte x) {
throw new ReadOnlyBufferException();
}
只是在写操作的方法里面,直接抛异常即可
4.wrap()
/**
* Wraps a byte array into a buffer.
*
* <p> The new buffer will be backed by the given byte array;
* that is, modifications to the buffer will cause the array to be modified
* and vice versa. The new buffer's capacity and limit will be
* <tt>array.length</tt>, its position will be zero, and its mark will be
* undefined. Its {@link #array backing array} will be the
* given array, and its {@link #arrayOffset array offset>} will
* be zero. </p>
*
* @param array
* The array that will back this buffer
*
* @return The new byte buffer
*/
public static ByteBuffer wrap(byte[] array) {
return wrap(array, 0, array.length);
}
返回以传入的数组为底层数组的buffer,修改buffer将会导致数组中的数据也会修改,反之亦然。
但是需要注意这样一点:
你既可以通过buffer来修改底层的字节数组,也可以直接操纵字节数组,这么做是比较危险的操作,除非
你要保证不会对已有的字节数组改动,都通过ByteByffer来进行操作,就不会有问题。
5.allocateDirect()
/**
* Allocates a new direct byte buffer.
*
* <p> The new buffer's position will be zero, its limit will be its
* capacity, its mark will be undefined, and each of its elements will be
* initialized to zero. Whether or not it has a {@link #hasArray backing array}
* is unspecified.
*/
public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
DirectByteBuffer和HeapByteBuffer有什么区别呢?
HeapByteBuffer :
在进行IO操作的时候多了一个拷贝到过程,会把Java堆内存中的数组拷贝到Java内存模型之外的操作系统的某块内存区域中,然后这块内存区域会直接的与IO设备进行交互。
DirectByteBuffer:
直接将数据存储在堆外内存,就减少了数组从java堆内向外拷贝的这一过程,简称零拷贝。
并且在DirectByteBuffer对象中,会有一个 long 类型的 adress 来存储数据所在的地址。但是为了访问方便,这个变量定义在了Buffer中。
// Used only by direct buffers
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
long address;
好处:
1)零拷贝
2)在gc的时候,如果是标记整理算法,那么在移动byte[]数组时,就会涉及copy,如果选择堆外内存就不会因为垃圾回收而复制。
堆外内存怎么释放呢?
在DirectByteBuffer被回收掉的时候