緩存區 Buffer 是數據容器
- ByteBuffer 可以存儲除了 boolean 以外的其他 7 種Java基本數據類型,如 getInt、putInt
- Buffer 是抽象類,它有除了 Boolean 以外的其他 7 種Java基本數據類型子類,如
IntBuffer
緩存區的初始化
⑴ 靜態方法 allocate:初始化一個指定容量的緩存區
解釋一下圖例:
1.數組下標:數字(1,2,3,4,5)表示數組下標
1.數組:灰色長方形內表示真實有效的數組。
2.數組元素:數字所在的白色黑邊正方形表示數組元素,可以通過例如 array[0] 來獲取數組元素。但是注意,圖中沒有明確指定數組元素的值是什么。
3.虛擬下標:其中-1
和6
是虛擬的下標位置,如果使用這2個下標取值( array[-1] 或者 array[6] )會拋出 IndexOutOfBoundsException
⑵ 靜態方法 wrap:把一個數組初始化成一個緩存區
- 如果是只把數組
array
作為 wrap 的參數,那么效果和 allocate 類似。但是,修改數組中的值,等同於修改緩存區的值。 - 如果除了數組引用
array
外,還有offset
和length
來指定子數組的開始位置和子數組的大小。效果如下圖:
- 灰色的部分就是數組參數
array
- 虛線框的部分表示從數組中划出的 子數組
緩存區存儲數據
put()
填充一個新的元素到數組中- 當前位置右移(position++)
緩沖區獲取數據
get()
獲取當前位置的元素- 當前位置右移(position++)
核心操作
flip 操作
由寫模式 轉換為> 讀模式
- limit = position,限制轉到原先的 position 位置
- position = 0,游標歸零
- mark = -1,標記清空
注意:
雖然,flip 的中文含義是 “翻動”,但是連續調用 flip 不能實現 寫模式 -> 讀模式 -> 寫模式!
連續調用 flip 之后,postion == limit == 0。
因此,繼續調用 get() 會拋出 讀取超限 BufferUnderflowException ,調用 put() 會拋出 寫入超限 BufferOverflowException
clear 操作
重新回到初始化狀態,重新進入寫模式
- limit = capacity,限制回歸到容器容量
- position = 0,游標歸零
- mark = -1,標記清空
注意
clear 實際並不會清理數據,而是調整 limit、position、mark 指向的位置
mark 操作
- mark = position,記錄下當前位置
使用場景
替換一段內容:添加標記,以便后續調用 reset() 將 position 回到標記。
reset 操作
- position = mark,當前位置回到標記位置
注意
mark < 0
拋出無效標記異常。說明必須要先 mark() 才能調用 reset()
rewind 操作
- position = 0,當前位置歸零
- mark = -1,清除標記位置
剩余空間與超限異常
剩余空間
其中,
remaining 表示剩余空間大小。hasRemaining() 用來查詢是否還有剩余空間。
讀取超限
- 在
get
讀取數據時,如果position >= limit
,拋出 BufferUnderflowException 異常
寫入超限
- 在
put
寫入數據時,如果position >= limit
,拋出 BufferOverflowException 異常
注意
如果是使用 wrap 初始化的緩沖區,即使沒有到達容器容量 capacity
,也會報錯,因為此時 limit < capacity
總結:
- Buffer緩沖區是數據容器,可以用於讀 get() 也可以用於寫 put()。
- flip() 可以從寫模式切換到讀模式
- clear() 可以回到初始化狀態
- mark() 和 reset() 需要配合使用,主要用於 替換某段內容
- 無論是讀取超限還是寫入超限,條件都是
position >= limit
。即 如果進行接下來的讀或者寫操作,當前位置都將超過限制。