NIO入門之緩沖區Buffer


緩存區 Buffer 是數據容器

buffer

  • ByteBuffer 可以存儲除了 boolean 以外的其他 7 種Java基本數據類型,如 getInt、putInt
  • Buffer 是抽象類,它有除了 Boolean 以外的其他 7 種Java基本數據類型子類,如IntBuffer

緩存區的初始化

⑴ 靜態方法 allocate:初始化一個指定容量的緩存區
allocate

解釋一下圖例:
1.數組下標:數字(1,2,3,4,5)表示數組下標
1.數組:灰色長方形內表示真實有效的數組。
2.數組元素:數字所在的白色黑邊正方形表示數組元素,可以通過例如 array[0] 來獲取數組元素。但是注意,圖中沒有明確指定數組元素的值是什么。
3.虛擬下標:其中 -16 是虛擬的下標位置,如果使用這2個下標取值( array[-1] 或者 array[6] )會拋出 IndexOutOfBoundsException

⑵ 靜態方法 wrap:把一個數組初始化成一個緩存區

  • 如果是只把數組 array 作為 wrap 的參數,那么效果和 allocate 類似。但是,修改數組中的值,等同於修改緩存區的值。
  • 如果除了數組引用 array 外,還有 offsetlength 來指定子數組的開始位置和子數組的大小。效果如下圖:

wrap

  • 灰色的部分就是數組參數 array
  • 虛線框的部分表示從數組中划出的 子數組

緩存區存儲數據

put

  • put() 填充一個新的元素到數組中
  • 當前位置右移(position++)

緩沖區獲取數據

get

  • get() 獲取當前位置的元素
  • 當前位置右移(position++)

核心操作

flip 操作

由寫模式 轉換為> 讀模式
flip

  • limit = position,限制轉到原先的 position 位置
  • position = 0,游標歸零
  • mark = -1,標記清空

注意:
雖然,flip 的中文含義是 “翻動”,但是連續調用 flip 不能實現 寫模式 -> 讀模式 -> 寫模式!
連續調用 flip 之后,postion == limit == 0。
因此,繼續調用 get() 會拋出 讀取超限 BufferUnderflowException ,調用 put() 會拋出 寫入超限 BufferOverflowException

clear 操作

重新回到初始化狀態,重新進入寫模式
clear

  • limit = capacity,限制回歸到容器容量
  • position = 0,游標歸零
  • mark = -1,標記清空

注意
clear 實際並不會清理數據,而是調整 limit、position、mark 指向的位置

mark 操作

mark

  • mark = position,記錄下當前位置

使用場景
替換一段內容:添加標記,以便后續調用 reset() 將 position 回到標記。

reset 操作

reset

  • position = mark,當前位置回到標記位置

注意
InvalidMarkException

  • mark < 0 拋出無效標記異常。說明必須要先 mark() 才能調用 reset()

rewind 操作

rewind

  • position = 0,當前位置歸零
  • mark = -1,清除標記位置

剩余空間與超限異常

剩余空間

\[0 <= 標記 <= 位置 <= 限制 <= 容量 \]

其中,

\[remaining = limit - position \]

remaining 表示剩余空間大小。hasRemaining() 用來查詢是否還有剩余空間。

讀取超限

BufferUnderflowException

  • get 讀取數據時,如果 position >= limit,拋出 BufferUnderflowException 異常

寫入超限

BufferOverflowException

  • put 寫入數據時,如果 position >= limit,拋出 BufferOverflowException 異常

注意
如果是使用 wrap 初始化的緩沖區,即使沒有到達容器容量 capacity,也會報錯,因為此時 limit < capacity
BufferOverflowException

總結:

  • Buffer緩沖區是數據容器,可以用於讀 get() 也可以用於寫 put()。
  • flip() 可以從寫模式切換到讀模式
  • clear() 可以回到初始化狀態
  • mark() 和 reset() 需要配合使用,主要用於 替換某段內容
  • 無論是讀取超限還是寫入超限,條件都是 position >= limit。即 如果進行接下來的讀或者寫操作,當前位置都將超過限制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM