Java NIO 建立/複製緩衝區
建立緩衝區的方式
主要有以下兩種方式建立緩衝區:
1、呼叫allocate方法
2、呼叫wrap方法
我們將以charBuffer為例,闡述各個方法的含義;
allocate方法建立緩衝區
呼叫allocate方法實際上會返回new HeapCharBuffer(capacity, capacity)物件;
快取空間儲存在CharBuffer類的成員屬性char[] hb數組裡,即JVM堆裡;
如下示例,建立了一個容量大小為10的CharBuffer:
CharBuffer bf = CharBuffer.allocate(10);
allocate方法其實比較簡單,不過有點需要注意的是,allocate方法除了可以分配JVM堆空間,還可以分配直接記憶體空間(如ByteBuffer,可以呼叫allocateDirect方法分配直接記憶體),其內部是通過呼叫unsafe.allocateMemory方法實現直接記憶體分配的,該空間不在JVM堆內部,後續會做更加詳細的說明;不過可以稍微提醒一點,如果是直接記憶體空間的話,呼叫hasArray()方法會返回false;
wrap方法建立緩衝區
呼叫wrap方法實際上會也會返回new HeapCharBuffer(array, offset, length)物件;
與allocate方法的區別是,它的快取儲存空間是外部傳入的;
如下示例,建立了一個容量大小為10的CharBuffer:
char[] myArray = new char[10]; CharBuffer charbuffer = CharBuffer.wrap(myArray);
另外,wrap還有一個過載方法:帶offset和length作為引數的wrap()方法,如下是該方法的一個示例:
char[] myArray = new char[10]; CharBuffer charbuffer = CharBuffer.wrap (myArray, 2, 3);
以上程式碼將會建立一個position = 2, limit = 5, capacity = 10的Buffer;
複製緩衝區的方式
主要有以下三種方式複製緩衝區:
1、呼叫duplicate方法
2、呼叫asReadOnlyBuffer方法
3、呼叫slice方法
我們將以charBuffer為例,闡述各個方法的含義;
duplicate方法複製緩衝區
呼叫duplicate方法實際上會建立原快取區的一個拷貝,不是深拷貝,是淺拷貝,什麼意思呢,就是這兩個快取區會共享資料元素,但每個快取區的上界、容量、位置等屬性是各自獨立的;
修改其中一個快取區的元素會影響另一個拷貝快取區,如下示例:
CharBuffer charbuffer1 = CharBuffer.allocate(10); CharBuffer charbuffer2 = charbuffer1.duplicate(); charbuffer1.put('a').put('b').put('c'); charbuffer1.flip(); System.out.println(charbuffer1); System.out.println(charbuffer2);
charbuffer2快取區複製了charbuffer1快取區,至始至終我們只操作charbuffer1快取區,最後列印的時候,卻發現charbuffer2快取區裡已經有了charbuffer1快取區的資料,結果列印如下:
abc
abc
asReadOnlyBuffer方法複製緩衝區
呼叫asReadOnlyBuffer方法會生成一個只讀快取區,與呼叫duplicate方法基本一致,唯一的區別是這個快取區是隻讀的,若對其進行put操作的話,會丟擲ReadOnlyBufferException;
如下示例:
CharBuffer charbuffer1 = CharBuffer.allocate(10); CharBuffer charbuffer2 = charbuffer1.asReadOnlyBuffer(); charbuffer1.put('a').put('b').put('c'); charbuffer1.flip(); System.out.println(charbuffer1); System.out.println(charbuffer2); charbuffer2.put('c');//ReadOnlyBufferException
輸出結果:
abc
abc
Exception in thread "main" java.nio.ReadOnlyBufferException
at java.nio.HeapCharBufferR.put(HeapCharBufferR.java:166)
at nio.Main.main(Main.java:21)
slice方法複製緩衝區
slice方法其實是用於分割快取區的,該方法建立了一個從原始緩衝區的當前位置開始的新緩衝區,並且其容量是原始緩衝區的剩餘元素數量(limit-position);
該快取區與原始快取區共享一段序列;
如下示例:
1、我們先建立一個容量為10的快取區charbuffer1
CharBuffer charbuffer1 = CharBuffer.allocate(10);
此時:mark = -1; position = 0; limit = 10; capacity = 10;
2、修改charbuffer1的position和limit值
charbuffer1.position(2).limit(5);
此時:mark = -1; position = 2; limit = 5; capacity = 10;
3、呼叫slice方法,對charbuffer1快取區進行分割
CharBuffer charbuffer2 = charbuffer1.slice();
此時:
charbuffer1:mark = -1; position = 2; limit = 5; capacity = 10;
charbuffer2:mark = -1; position = 0; limit = 3; capacity = 3;