版本:JDK7
package java.nio;
public abstract class ByteBuffer extends Buffer implements Comparable
// These fields are declared here rather than in Heap-X-Buffer in order to
// reduce the number of virtual method invocations needed to access these
// values, which is especially costly when coding small buffers.
//
final byte[] hb; // Non-null only for heap buffers
final int offset;
boolean isReadOnly; // Valid only for heap buffers
ByteBuffer(int mark, int pos, int lim, int cap, byte[] hb, int offset) {
super(mark, pos, lim, cap);
this.hb = hb;
this.offset = offset;
}
ByteBuffer(int mark, int pos, int lim, int cap) { // package-private
this(mark, pos, lim, cap, null, 0);
}
// 创建一个容量为capacity的ByteBuffer对象
public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
// 创建一个容量为capacity的ByteBuffer对象
public static ByteBuffer allocate(int capacity) {
if (capacity < 0) throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
public static ByteBuffer wrap(byte[] array, int offset, int length) {
try {
return new HeapByteBuffer(array, offset, length);
} catch (IllegalArgumentException x) {
throw new IndexOutOfBoundsException();
}
}
public static ByteBuffer wrap(byte[] array) {
return wrap(array, 0, array.length);
}
public abstract ByteBuffer slice();
public abstract ByteBuffer duplicate();
public abstract ByteBuffer asReadOnlyBuffer();
/**
* Reads the byte at this buffer's position, and then increments the position.
*/
// 读取单个字节,并将position自增1
public abstract byte get();
/**
* Writes the given byte into this buffer at the current position, and then increments the position.
*/
// 将给定的单个字节写入缓冲区的当前位置,并将position自增1
public abstract ByteBuffer put(byte b);
// 读取指定位置的字节,注意:不会改变position
public abstract byte get(int index);
// 将给定的单个字节写入缓冲区的index位置,注意:不会改变position
public abstract ByteBuffer put(int index, byte b);
// -- Bulk get operations --
/**
* This method transfers bytes from this buffer into the given destination array.
*/
// (从Buffer中)读取多个字节(从索引offset开始,读取length长度的数据)到dst中,如果Buffer剩余的空间小于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;
}
/**
* This method transfers bytes from this buffer into the given destination array.
*/
// 批量读取dst.length个字节到dst中,如果Buffer剩余的空间小于dst的length,则抛异常
public ByteBuffer get(byte[] dst) {
return get(dst, 0, dst.length);
}
// -- Bulk put operations --
/**
* 将src中的数据写入Buffer的当前位置
*/
public ByteBuffer put(ByteBuffer src) {
if (src == this)
throw new IllegalArgumentException();
int n = src.remaining();
if (n > remaining())
throw new BufferOverflowException();
for (int i = 0; i < n; i++)
put(src.get());
return this;
}
public ByteBuffer put(byte[] src, int offset, int length) {
checkBounds(offset, length, src.length);
if (length > remaining())
throw new BufferOverflowException();
int end = offset + length;
for (int i = offset; i < end; i++)
this.put(src[i]);
return this;
}
public final ByteBuffer put(byte[] src) {
return put(src, 0, src.length);
}
// -- Other stuff --
/**
* Tells whether or not this buffer is backed by an accessible byte array.
*
* <p> If this method returns <tt>true</tt> then the {[@link](https://my.oschina.net/u/393) #array() array}
* and {[@link](https://my.oschina.net/u/393) #arrayOffset() arrayOffset} methods may safely be invoked.
* </p>
*
* [@return](https://my.oschina.net/u/556800) <tt>true</tt> if, and only if, this buffer
* is backed by an array and is not read-only
*/
public final boolean hasArray() {
return (hb != null) && !isReadOnly;
}
/**
* Returns the byte array that backs this
* buffer <i>(optional operation)</i>.
*
* <p> Modifications to this buffer's content will cause the returned
* array's content to be modified, and vice versa.
*
* <p> Invoke the {[@link](https://my.oschina.net/u/393) #hasArray hasArray} method before invoking this
* method in order to ensure that this buffer has an accessible backing
* array. </p>
*
* [@return](https://my.oschina.net/u/556800) The array that backs this buffer
*
* @throws ReadOnlyBufferException
* If this buffer is backed by an array but is read-only
*
* @throws UnsupportedOperationException
* If this buffer is not backed by an accessible array
*/
public final byte[] array() {
if (hb == null) throw new UnsupportedOperationException();
if (isReadOnly) throw new ReadOnlyBufferException();
return hb;
}
/**
* Returns the offset within this buffer's backing array of the first
* element of the buffer <i>(optional operation)</i>.
*
* <p> If this buffer is backed by an array then buffer position <i>p</i>
* corresponds to array index <i>p</i> + <tt>arrayOffset()</tt>.
*
* <p> Invoke the {@link #hasArray hasArray} method before invoking this
* method in order to ensure that this buffer has an accessible backing
* array. </p>
*
* @return The offset within this buffer's array
* of the first element of the buffer
*
* @throws ReadOnlyBufferException
* If this buffer is backed by an array but is read-only
*
* @throws UnsupportedOperationException
* If this buffer is not backed by an accessible array
*/
public final int arrayOffset() {
if (hb == null) throw new UnsupportedOperationException();
if (isReadOnly) throw new ReadOnlyBufferException();
return offset;
}
/**
* Compacts this buffer. 压缩并整理Buffer。
*
* The bytes between the buffer's current position and its limit, if any, are copied to the beginning of the buffer.
* That is, the byte at index p=position() is copied to index zero,
* the byte at index p+1 is copied to index one,
* and so forth until the byte at index limit()-1 is copied to index n=limit()-1-p
* The buffer's position is then set to n+1 and its limit is set to its capacity. The mark, if defined, is discarded.
*
* 即:将所有未读的数据拷贝到Buffer的起始处,然后将position设到最后一个未读元素的后面
* limit设置为capacity,此时,如果向Buffer中写数据,则不会覆盖之前未读的数据!
* 与clear()方法的比较:
* 如果Buffer中存在未读的数据,调用clear()方法后,这些未读的数据将会被“遗忘”,因为在clear之后,position的值为0,故无法确定未读数据的位置。
*/
public abstract ByteBuffer compact();
/**
* Tells whether or not this byte buffer is direct. </p>
*/
public abstract boolean isDirect();
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append("[pos=");
sb.append(position());
sb.append(" lim=");
sb.append(limit());
sb.append(" cap=");
sb.append(capacity());
sb.append("]");
return sb.toString();
}
/**
* Returns the current hash code of this buffer.
*/
public int hashCode() {
int h = 1;
int p = position();
for (int i = limit() - 1; i >= p; i--)
h = 31 * h + (int)get(i);
return h;
}
/**
* Tells whether or not this buffer is equal to another object.
*
* They have the same element type,
* They have the same number of remaining elements,
* and The two sequences of remaining elements,
* considered independently of their starting positions, are pointwise equal.
*
* 即:Buffer中元素的类型相同,并且剩余的元素完全相同,则返回true
* 注意:并不是比较Buffer的所有数据,只是比较Buffer中的剩余数据。
*/
public boolean equals(Object ob) {
if (this == ob)
return true;
if (!(ob instanceof ByteBuffer))
return false;
ByteBuffer that = (ByteBuffer)ob;
if (this.remaining() != that.remaining())
return false;
int p = this.position();
for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
if (!equals(this.get(i), that.get(j)))
return false;
return true;
}
private static boolean equals(byte x, byte y) {
return x == y;
}
/**
* Compares this buffer to another.
*
* 比较两个Buffer的剩余元素
* 一个Buffer“小于”另一个Buffer的场景:
* 第一个不相等的元素小于另一个Buffer中对应的元素
* 所有元素都相等,但是第一个Buffer的元素个数小于另一个Buffer的个数
*/
public int compareTo(ByteBuffer that) {
int n = this.position() + Math.min(this.remaining(), that.remaining());
for (int i = this.position(), j = that.position(); i < n; i++, j++) {
int cmp = compare(this.get(i), that.get(j));
if (cmp != 0)
return cmp;
}
return this.remaining() - that.remaining();
}
private static int compare(byte x, byte y) {
return Byte.compare(x, y);
}
// -- Other char stuff --
// -- Other byte stuff: Access to binary data --
boolean bigEndian = true; // package-private
boolean nativeByteOrder = (Bits.byteOrder() == ByteOrder.BIG_ENDIAN); // package-private
/**
* Retrieves this buffer's byte order.
*
* <p> The byte order is used when reading or writing multibyte values, and
* when creating buffers that are views of this byte buffer. The order of
* a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN
* BIG_ENDIAN}. </p>
*
* @return This buffer's byte order
*/
public final ByteOrder order() {
return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
}
/**
* Modifies this buffer's byte order. </p>
*
* @param bo
* The new byte order,
* either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
* or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
*
* @return This buffer
*/
public final ByteBuffer order(ByteOrder bo) {
bigEndian = (bo == ByteOrder.BIG_ENDIAN);
nativeByteOrder = (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN));
return this;
}
// Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
//
abstract byte _get(int i); // package-private
abstract void _put(int i, byte b); // package-private
/**
* Relative <i>get</i> method for reading an int value.
*
* <p> Reads the next four bytes at this buffer's current position,
* composing them into an int value according to the current byte order,
* and then increments the position by four. </p>
*
* @return The int value at the buffer's current position
*
* @throws BufferUnderflowException
* If there are fewer than four bytes
* remaining in this buffer
*/
public abstract int getInt();
/**
* Relative <i>put</i> method for writing an int
* value <i>(optional operation)</i>.
*
* <p> Writes four bytes containing the given int value, in the
* current byte order, into this buffer at the current position, and then
* increments the position by four. </p>
*
* @param value
* The int value to be written
*
* @return This buffer
*
* @throws BufferOverflowException
* If there are fewer than four bytes
* remaining in this buffer
*
* @throws ReadOnlyBufferException
* If this buffer is read-only
*/
public abstract ByteBuffer putInt(int value);
/**
* Absolute <i>get</i> method for reading an int value.
*
* <p> Reads four bytes at the given index, composing them into a
* int value according to the current byte order. </p>
*
* @param index
* The index from which the bytes will be read
*
* @return The int value at the given index
*
* @throws IndexOutOfBoundsException
* If <tt>index</tt> is negative
* or not smaller than the buffer's limit,
* minus three
*/
public abstract int getInt(int index);
/**
* Absolute <i>put</i> method for writing an int
* value <i>(optional operation)</i>.
*
* <p> Writes four bytes containing the given int value, in the
* current byte order, into this buffer at the given index. </p>
*
* @param index
* The index at which the bytes will be written
*
* @param value
* The int value to be written
*
* @return This buffer
*
* @throws IndexOutOfBoundsException
* If <tt>index</tt> is negative
* or not smaller than the buffer's limit,
* minus three
*
* @throws ReadOnlyBufferException
* If this buffer is read-only
*/
public abstract ByteBuffer putInt(int index, int value);
/**
* Creates a view of this byte buffer as an int buffer.
*
* <p> The content of the new buffer will start at this buffer's current
* position. Changes to this buffer's content will be visible in the new
* buffer, and vice versa; the two buffers' position, limit, and mark
* values will be independent.
*
* <p> The new buffer's position will be zero, its capacity and its limit
* will be the number of bytes remaining in this buffer divided by
* four, and its mark will be undefined. The new buffer will be direct
* if, and only if, this buffer is direct, and it will be read-only if, and
* only if, this buffer is read-only. </p>
*
* @return A new int buffer
*/
public abstract IntBuffer asIntBuffer();
// ...
}