下面通過分析java nio的Buffer類的源代碼來學習Buffer中的position、limit、capcity和marker幾個标志位的變化。源代碼分析如下:public abstract class Buffer {
// 變量的取值限制: mark <= position <= limit <= capacity
private int mark = -1; // 标記
private int position = 0; // 目前位置
private int limit; // 限制
private int capacity; // 容量
……
}
上面是Buffer.java類定義的變量,其中這些變量儲存了緩沖區的狀态。
Buffer類的構造方法,代碼如下:// 使用指定參數建立一個Buffer執行個體
Buffer(int mark, int pos, int lim, int cap) { // package-private
// 容量不能小于0
if (cap
throw new IllegalArgumentException("Negative capacity: " + cap);
this.capacity = cap;
limit(lim);
position(pos);
// 标記必須大于等于0且小于目前位置
if (mark >= 0) {
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("
+ mark + " > " + pos + ")");
this.mark = mark;
}
}
這個構造方法中設定了緩沖區的容量、限制、目前位置和标記。
當Buffer接收使用者寫入資料時,預設的狀态是position=1,capacity=limit。如下圖:

向緩沖區中輸入資料,此時緩沖區中的position狀态會發生改變,每多輸入一個位元組position就會自動加1,如下圖是緩沖區寫入一部分資料後,緩沖區的狀态。
當資料輸入完畢(指緩沖區已滿或資料已經輸入完),此時需要調用flip方法将緩沖區進行反轉,即設定目前位置position=0,限制limit等于position(緩沖區資料容量),源碼如下:// 反轉緩沖區,即為讀取資料做好準備(設定标志)
// 将限制設定為目前位置,再将目前位置設定為緩沖區開始0,清除标記。
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
下圖為從緩沖區中讀入一部分資料後的狀态圖:
使用mark方法對已經讀入的資料進行标記,标記後你可以通過reset方法重置到mark标記處,下面是mark的源碼:// 設定标記為目前位置
public final Buffer mark() {
mark = position;
return this;
}
上圖是設定标記後,繼續讀取一部分資料後緩沖區的狀态。設定标記的目的就是在以後可以傳回到标記處重新讀取标記後面的資料,要想将目前位置推回到标記處,隻需要調用reset方法,源代碼如下:// 将目前位置設定為标記值
public final Buffer reset() {
int m = mark;
if (m
throw new InvalidMarkException();
position = m;
return this;
}
重置後的緩沖區狀态圖: