Android坑点-ByteBuffer.array() 入过坑吗
目錄
- 1、坑點(diǎn)介紹
- 2、正確使用姿勢(入坑了怎么辦)
- 3、坑坑詳解
- 3.1HeapByteBuffer可以用buffer.array()
- 3.2DirectByteBuffer的坑在哪里
1、坑點(diǎn)介紹
如下代碼:
ByteBuffer buffer = ByteBuffer.allocateDirect(int capacity) byte[] array = buffer.array()在android平臺前面會(huì)有幾個(gè)字節(jié)是沒有實(shí)際數(shù)據(jù)的,在jre環(huán)境下,發(fā)生異常。
怎么理解呢?
來個(gè)栗子:
結(jié)果如下:
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[0]=0
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[1]=0
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[2]=0
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[3]=0
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[4]=1
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[5]=2
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[6]=0
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[7]=0
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[8]=0
2021-10-27 15:29:43.169 D/BufferTester: bufferTest arr[9]=0
通過上面的結(jié)果可以看到 arr[4]=1, arr[5]=2。我們是put了1和2,正常情況是從數(shù)組第一個(gè)元素開始寫入,我們?nèi)〕龅臄?shù)組卻跳躍了前面4個(gè)字節(jié)。
2、正確使用姿勢(入坑了怎么辦)
實(shí)際上buffer.array() 是不能用的,我們需要使用get(byte[] dst) 或get(byte[] dst, int offset, int length),具體代碼如下
private void bufferTest() {ByteBuffer buffer = ByteBuffer.allocateDirect(10);buffer.put((byte) 1);buffer.put((byte) 2); // byte[] arr = buffer.array();buffer.position(0);byte []arr = new byte[10];//put 2次,實(shí)際是2個(gè)字節(jié)buffer.get(arr);for (int i = 0; i < 10; i++) {Log.d("BufferTester", "bufferTest arr[" + i + "]=" + arr[i]);}}結(jié)果:
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[0]=1
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[1]=2
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[2]=0
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[3]=0
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[4]=0
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[5]=0
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[6]=0
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[7]=0
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[8]=0
2021-10-27 15:53:49.954 D/BufferTester: bufferTest arr[9]=0
arr[0]=1,arr[1]=2 是我們期望的結(jié)果,也是正確結(jié)果。
注:put一字節(jié),postion+1,所以上述代碼在取的時(shí)候,將pos恢復(fù)到起始位置。
所以請使用get方法來獲取內(nèi)容。
如果還是要用array(),那么一定要完全掌握好DirectByteBuffer的機(jī)制。
3、坑坑詳解
ByteBuffer是一個(gè)抽象類,通過類函數(shù) allocateDirect(int capacity)創(chuàng)建的是DirectByteBuffer對象;通過類函數(shù)allocate(int capacity)創(chuàng)建的是HeapByteBuffer對象。關(guān)系和代碼如下
簡單過一下:HeapByteBuffer 是堆上分配的空間,DirectByteBuffer是系統(tǒng)分配的空間。
3.1HeapByteBuffer可以用buffer.array()
private HeapByteBuffer(int cap, int lim, boolean isReadOnly) {super(-1, 0, lim, cap, new byte[cap], 0);this.isReadOnly = isReadOnly;}因?yàn)檎{(diào)用super的時(shí)候,就 按照給定的大小(new byte[cap]) 分配了數(shù)組傳遞給父類,最終調(diào)用array()的時(shí)候,就返回的這個(gè)數(shù)組。
3.2DirectByteBuffer的坑在哪里
注意了,我們重點(diǎn)看兩個(gè)構(gòu)造函數(shù)
DirectByteBuffer.MemoryRef memoryRef = new DirectByteBuffer.MemoryRef(capacity);
return new DirectByteBuffer(capacity, memoryRef);
注意看注釋要點(diǎn)1、2、3:
也許老鐵已經(jīng)看出了端倪,此處傳遞給父類的數(shù)組是capacity + 7長度的,其中address是數(shù)組的一個(gè)子集,舉個(gè)例子,如果capacity = 10,offset = 5,那么buffer的長度是17,allocatedAddress 是buffer[0]的地址,address 就是buffer[5] 地址。
總體來說DirectByteBuffer分配了一個(gè)字節(jié)數(shù)組buffer 長度capacity+7,并計(jì)算出了一個(gè)小于7的偏移值x,再得到一個(gè)buffer的偏移地址,address = buffer+x。put、get都是通過address來存取的,因偏移,存取起始位置不一定是buffer[0],array() 返回的是buffer,因此可能存在前面x個(gè)字節(jié)沒有值。
參數(shù)給的10,buffer實(shí)際長度17:
2021-10-27 17:18:14.740 D/BufferTester: bufferTest len = 17
同時(shí)在jre的環(huán)境下,DirectByteBuffer的實(shí)現(xiàn)稍有區(qū)別,沒有偏移,且array被調(diào)用會(huì)拋出異常。沒有計(jì)算offset也沒有持有數(shù)組對象,只通過一個(gè)地址進(jìn)行存取。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Android坑点-ByteBuffer.array() 入过坑吗的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从零开始学java 框架_从零开始学 J
- 下一篇: Android面试基础一