我們到底能走多遠系列(18)
扯淡:最近想要跳槽,現公司的主管不高興,沒提的時候關係好像很好,提的時候我比較堅決,他硬要我留一個月,老實說我想弄個三周就好了,對,國際慣例一個月,我也是想砍個一周下來休息下,他居然恐嚇我,表達出我不仁他就不義的態度,表示可以再沒走的時候為難我。現在開始挑我工作毛病了,態度已經不行了,有點裝不住了,哈哈。我想,你這麼搞我,我交接也不會盡全力了的,做到本職就滾蛋,留下的坑,你們慢慢填。
最近一個月,經曆了些事情,又教育了我一邊,要投資自己,讓自己變強,才能在有風雨時不倒。僥倖想在別人的樹下躲避風雨的,今天可能過了關,包不好明天能不能過。我覺得,不要受制於人的要求是有點高,能做到不完全受制於人已經不錯了。
主題:
關於NIO的基本知識在(系列17)記錄過了,繼續來瞭解下Buffer
Buffer API:
int capacity()//返回此緩衝區的容量。 Buffer clear()//清除此緩衝區。 Buffer flip()//反轉此緩衝區。 boolean hasRemaining()//判斷在當前位置和限制之間是否有任何元素。 abstract boolean isReadOnly()//判斷此緩衝區是否為唯讀緩衝區。 int limit()//返回此緩衝區的限制。 Buffer limit(int newLimit)//設定此緩衝區的限制。 Buffer mark()//在此緩衝區的位置設定其標記。 int position()//返回此緩衝區的位置。 Buffer position(int newPosition)//設定此緩衝區的位置。 int remaining()//返回當前位置與限制之間的元素數量。 Buffer reset()//將此緩衝區的位置重新設定成以前標記的位置。 Buffer rewind()//重繞此緩衝區。
直接看源碼,關於其中的flip和clear方法在系列17中詳細學習了。
public abstract class Buffer { // Invariants: mark <= position <= limit <= capacity private int mark = -1; // 一個備忘位置 private int position = 0; // 位置,下一個要被讀或寫的元素的索引,根據它來決定讀哪個位置 private int limit; // 上界,緩衝區的第一個不能被讀或寫的元素。 private int capacity; // 緩衝區容量。緩衝區建立時被設定,並且永遠不能被改變。 // 初始化 Buffer(int mark, int pos, int lim, int cap) { // package-private if (cap < 0) throw new IllegalArgumentException(); this.capacity = cap; limit(lim); position(pos); if (mark >= 0) { if (mark > pos) throw new IllegalArgumentException(); this.mark = mark; } } public final int capacity() { return capacity; } public final int position() { return position; } public final Buffer position(int newPosition) { if ((newPosition > limit) || (newPosition < 0)) throw new IllegalArgumentException(); position = newPosition; if (mark > position) mark = -1; // 因為重新設定position,mark可能超過它,索性把mark還原 // 返回設定好後新的自己 // 這種返回自己的方式可以實現支援級聯調用,比如buffer.mark().position(5).reset( ); return this; } public final int limit() { return limit; } public final Buffer limit(int newLimit) { if ((newLimit > capacity) || (newLimit < 0)) throw new IllegalArgumentException(); limit = newLimit; // limit的設定牽涉到下面兩個:position和mark if (position > limit) position = limit; if (mark > limit) mark = -1; return this; } public final Buffer mark() { mark = position; return this; } public final Buffer reset() { int m = mark; if (m < 0) throw new InvalidMarkException(); position = m;// 把position設定到mark的位置,下一次讀資料的時候就可以,從mark的位置讀起了。 return this; } public final Buffer clear() { position = 0; // position清零 limit = capacity; // limit初始化 mark = -1; // mark初始化 // 三步操作這個Buffer又重生了。可以繼續用了。下一次寫入,就是覆蓋即可。 // 注意clear方法返回了自己,因為clear方法沒有真正意義上clear自己的內容,如果這時候我們操作返回的buffer,這個buffer是有內容的。 return this; } public final Buffer flip() { limit = position; position = 0; mark = -1; return this; } public final Buffer rewind() { position = 0;// 和clear()操作不同的是少了limit初始化,如此即可實現對這個buffer的重讀 mark = -1; return this; } //返回當前位置與限制之間的元素數量。 public final int remaining() { return limit - position; } //判斷在當前位置和限制之間是否有任何元素。 public final boolean hasRemaining() { return position < limit; } // 所有的緩衝區都是可讀的,但並非所有都可寫。 public abstract boolean isReadOnly(); // 後面還有nextGetIndex(),nextGetIndex(int nb) 等方法,因為是不是對外提供的方法,就不進一步介紹了。}
ByteBuffer的API:
1,HeapByteBuffer中實現了抽象類別ByteBuffer中為實現的方法。
2,ByteBuffer中的get set 方法就是對一個數組的操作。
get的四個方法:
get();
get (int index);
get(byte[] dst);
get(byte[] dst, int offset, int length);
前兩個方法比較好理解,返回的是取得的內容,後面兩個方法是將此緩衝區的位元組傳輸到給定的目標數組中。
來看下源碼:
public ByteBuffer get(byte[] dst) { return get(dst, 0, dst.length);} public ByteBuffer get(byte[] dst, int offset, int length) { checkBounds(offset, length, dst.length); if (length > remaining()) throw new BufferUnderflowException(); int end = offset + length; // 最後還是一個個拿 for (int i = offset; i < end; i++) dst[i] = get(); return this;}
put方法API:
abstract ByteBuffer put(byte b)
ByteBuffer put(byte[] src)
ByteBuffer put(byte[] src, int offset, int length)
ByteBuffer put(ByteBuffer src)
abstract ByteBuffer put(int index, byte b)
壓縮方法:
public abstract ByteBuffer compact( );
看,使用前:
使用後: