java nio ByteBuffer源码分析
程序员文章站
2022-03-15 20:59:26
目录简介字段hb,offset,isReadOnly,2个构造函数方法allocateDirect,allocate,2个wrap,slice,duplicate,asReadOnlyBuffer方法4个get,5个put方法array,arrayOffset,compact,isDirect,toString,hashCode,2个equals,compareTo字段bigEndian,nativeByteOrder,方法order,_get,_put方法getXXX,putX...
目录
方法allocateDirect,allocate,2个wrap,slice,duplicate,asReadOnlyBuffer
方法array,arrayOffset,compact,isDirect,toString,hashCode,2个equals,compareTo
字段bigEndian,nativeByteOrder,方法order,_get,_put
方法getXXX,putXXX,asXXXBuffer(char,short,int,long,float,double)
简介
package java.nio;
/**
* 字节缓冲区。
*
* <p>
* 此类在字节缓冲区上定义了六类操作:
*
* <ul>
*
* <li>
* <p>
* 读写单个字节的绝对和相对get和put方法;
* </p>
* </li>
*
* <li>
* <p>
* 将连续字节序列从该缓冲区传输到数组中的相对批量get(byte[])方法;
* </p>
* </li>
*
* <li>
* <p>
* 将连续字节序列从字节数组或其他字节缓冲区传输到该缓冲区的相对批量put(byte[])方法;
* </p>
* </li>
*
*
* <li>
* <p>
* 绝对和相对getChar和putChar方法等,用于读取和写入其他原始类型的值,并以特定字节顺序在字节序列之间进行转换;
* </p>
* </li>
*
* <li>
* <p>
* 创建视图缓冲区的方法,允许将字节缓冲区视为包含其他某种原始类型值的缓冲区;以及
* </p>
* </li>
*
*
* <li>
* <p>
* 压缩、复制和切片字节缓冲区的方法。
* </p>
* </li>
*
* </ul>
*
* <p>
* 字节缓冲区可以通过allocate(为缓冲区的内容分配空间)来创建,
*也可以通过wrap(byte[]),将现有的字节数组包装到缓冲区来创建。
*
* <a name="direct"></a>
* <h2>直接缓冲区与非直接缓冲区</h2>
*
* <p>
* 字节缓冲区可以是直接缓冲区,也可以是非直接缓冲区。
* 给定一个直接字节缓冲区,Java虚拟机将尽最大努力直接在其上执行I/O操作。
* 也就是说,它将尝试避免在每次调用底层操作系统的本地IO操作,之前或之后,
* 将缓冲区的内容复制到,或从,中间缓存区。
*
*
* <p>
* 直接字节缓冲区可以通过调用此类的allocateDirect(int)工厂方法来创建。
* 此方法返回的缓冲区通常比非直接缓冲区具有更高的分配和释放成本。
* 直接缓冲区的内容可能位于普通垃圾收集堆之外,因此它们对应用程序内存占用的影响可能并不明显。
* 因此,建议将直接缓冲区主要分配给大型、长寿命的缓冲区,这些缓冲区受底层系统本机I/O操作的影响。
* 一般来说,只有当直接缓冲区在程序性能上获得可测量的增益时,才最好分配直接缓冲区。
*
* <p>
* 直接字节缓冲区也可以通过FileChannel的map方法,映射文件的一个区域到内存。
* Java平台的实现可以选择支持通过JNI从本机代码创建直接字节缓冲区。
* 如果其中一种缓冲区的实例引用了内存的不可访问区域,则尝试访问该区域
* 不会更改缓冲区的内容,并将导致在访问时或稍后某个时间引发未指定的异常。
*
* <p>
* 字节缓冲区是直接的还是非直接的,可以通过调用它的isDirect方法来确定。
* 提供此方法是为了在性能关键代码中执行显式缓冲区管理。
*
*
* <a name="bin"></a>
* <h2>访问二进制数据</h2>
*
* <p>
* 这个类定义了读取和写入除boolean之外的所有其他基元类型的值的方法。
* 基本类型值根据缓冲区的当前字节顺序,转换为(或从)字节序列,这些字节序列可以通过order方法进行检索和修改。
* 特定字节顺序由ByteOrder类的实例表示。初始字节的顺序始终是BIG_ENDIAN。
*
* <p>
* 为了访问异构二进制数据,即不同类型的值序列,
* 此类为每种类型定义了一系列绝对和相对的get和put方法。
* 例如,对于32位浮点值,此类定义:
*
* <blockquote>
*
* <pre>
* float {@link #getFloat()}
* float {@link #getFloat(int) getFloat(int index)}
* void {@link #putFloat(float) putFloat(float f)}
* void {@link #putFloat(int,float) putFloat(int index, float f)}
* </pre>
*
* </blockquote>
*
* <p>
* 为char、short、int、long和double类型定义了相应的方法。
* 绝对get和put方法的参数index是以字节为单位的,而不是被读取或写入的类型。
*
* <a name="views"></a>
*
* <p>
* 对于同一类型的数据,这个类定义了即根据给定的字节缓冲区,创建视图的方法。
* 视图缓冲区只是另一个其内容由字节缓冲区支持的缓冲区。
* 对字节缓冲区内容的更改将在视图缓冲区中可见,反之亦然;
* 两个缓冲区的位置、限制和标记值是独立的。
* 例如,asFloatBuffer方法,创建FloatBuffer类的一个实例,该实例由该方法所在的字节缓冲区支持调用。
* 对应视图创建方法是为char、short、int、long和double类型定义的。
*
* <p>
* 与类型特定的get和put方法系列相比,视图缓冲区有三个重要优势:
*
* <ul>
*
* <li>
* <p>
* 视图缓冲区的索引不是根据字节,而是根据其值的类型特定大小;
* </p>
* </li>
*
* <li>
* <p>
* 视图缓冲区提供相对批量获取和放置方法,
* 可以在缓冲区和数组或其他同类缓冲区之间传输连续的值序列;以及
* </p>
* </li>
*
* <li>
* <p>
* 如果它是直接缓冲区,那么它的直接缓冲区可能更有效。
* </p>
* </li>
*
* </ul>
*
* <p>
* 视图缓冲区的字节顺序固定为创建视图时其字节缓冲区的字节顺序。
* </p>
*
* <h2>引用链</h2>
*
* <p>
* 该类中不需要返回值的方法被指定为返回调用它们的缓冲区。
* 这允许方法调用被链接。
*
* 语句序列
*
* <blockquote>
*
* <pre>
* bb.putInt(0xCAFEBABE);
* bb.putShort(3);
* bb.putShort(45);
* </pre>
*
* </blockquote>
*
* can, for example, be replaced by the single statement
*
* <blockquote>
*
* <pre>
* bb.putInt(0xCAFEBABE).putShort(3).putShort(45);
* </pre>
*
* </blockquote>
*
*
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
*/
public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>
字段hb,offset,isReadOnly,2个构造函数
// 这些字段是在这里声明的,而不是在Heap-X-Buffer中声明的,
// 目的是减少访问这些值所需的虚方法调用的数量,在编写小型缓冲区时,这样做的代价特别高。
final byte[] hb; // 非空仅用于堆缓冲区
final int offset; // hb的偏移量
boolean isReadOnly; // 仅对堆缓冲区有效
// 使用给定的标记、位置、限制、容量、后备数组和数组偏移量创建一个新的缓冲区
ByteBuffer(int mark, int pos, int lim, int cap, // package-private
byte[] hb, int offset) {
// 设置6个值
super(mark, pos, lim, cap);
this.hb = hb;
this.offset = offset;
}
// 使用给定的标记、位置、限制和容量创建一个新的缓冲区
// hb为null,offset为0
ByteBuffer(int mark, int pos, int lim, int cap) { // package-private
this(mark, pos, lim, cap, null, 0);
}
方法allocateDirect,allocate,2个wrap,slice,duplicate,asReadOnlyBuffer
/**
* 分配一个新的直接字节缓冲区。
*
* <p>
* 新缓冲区的位置将为零,它的限制将为它的容量,
* 它的标记将未定义,它的每个元素将初始化为零。
* 它是否有后备数组未指定。
*
* @param capacity The new buffer's capacity, in bytes
*
* @return The new byte buffer
*
* @throws IllegalArgumentException If the <tt>capacity</tt> is a negative
* integer
*/
public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
/**
* 分配一个新的字节缓冲区。
*
* <p>
* 新缓冲区的位置将为零,它的限制将为它的容量,
* 它的标记将未定义,它的每个元素将初始化为零。
* 它将有一个后备数组,它的数组偏移量将为零。
*
* @param capacity The new buffer's capacity, in bytes
*
* @return The new byte buffer
*
* @throws IllegalArgumentException If the <tt>capacity</tt> is a negative
* integer
*/
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
/**
* 将字节数组包装到缓冲区中。
*
* <p>
* 新的缓冲区将由给定的字节数组支持;
* 也就是说,对缓冲区的修改将导致数组被修改,反之亦然。
* 新的缓冲区的容量将是array.length,其位置为offset,其限制为offset + length,其标记将未定义。
* 它的后备数组将是给定的数组,它的数组偏移量将为零。
* </p>
*
* @param array The array that will back the new buffer
*
* @param offset The offset of the subarray to be used; must be non-negative and
* no larger than <tt>array.length</tt>. The new buffer's position
* will be set to this value.
*
* @param length The length of the subarray to be used; must be non-negative and
* no larger than <tt>array.length - offset</tt>. The new buffer's
* limit will be set to <tt>offset + length</tt>.
*
* @return The new byte buffer
*
* @throws IndexOutOfBoundsException If the preconditions on the <tt>offset</tt>
* and <tt>length</tt> parameters do not hold
*/
public static ByteBuffer wrap(byte[] array, int offset, int length) {
try {
return new HeapByteBuffer(array, offset, length);
} catch (IllegalArgumentException x) {
throw new IndexOutOfBoundsException();
}
}
/**
* 将字节数组包装到缓冲区中。
*
* <p>
* 新的缓冲区将由给定的字节数组支持;
* 也就是说,对缓冲区的修改将导致数组被修改,反之亦然。
* 缓冲区的容量和限制将是array.length,其位置为0,其标记为未定义。
* 它的后备数组将是给定的数组,它的数组偏移将为0。
* </p>
*
* @param array The array that will back this buffer
*
* @return The new byte buffer
*/
public static ByteBuffer wrap(byte[] array) {
return wrap(array, 0, array.length);
}
/**
* 创建一个新的字节缓冲区,其内容是这个缓冲区内容的共享子序列。
*
* <p>
* 新缓冲区的内容将从该缓冲区的当前位置开始。
* 对该缓冲区内容的更改将在新缓冲区中可见,反之亦然;
* 这两个缓冲区的位置、限制和标记值将是独立的。
*
* <p>
* 新缓冲区的位置将为零,其容量和限制将为该缓冲区中剩余的字节数,其标记将未定义。
* 当且仅当此缓冲区是直接的,新缓冲区将是直接的,当且仅当此缓冲区是只读的,它将是只读的。
* </p>
*
* @return The new byte buffer
*/
public abstract ByteBuffer slice();
/**
* 创建一个共享该缓冲区内容的新字节缓冲区。
*
* <p>
* 新缓冲区的内容将是这个缓冲区的内容。
* 这个缓冲区内容的变化将在新的缓冲区中可见,反之亦然;
* 两个缓冲区的位置、限制和标记值将是独立的。
*
* <p>
* 新缓冲区的容量、限制、位置和标记值与此缓冲区的相同。
* 新缓冲区将是直接的,当且仅当,这个缓冲区是直接的。
* 它将是只读的,当且仅当,这个缓冲区是只读的。
* </p>
*
* @return The new byte buffer
*/
public abstract ByteBuffer duplicate();
/**
* 创建一个共享该缓冲区内容的新的只读字节缓冲区。
*
* <p>
* 新缓冲区的内容将是这个缓冲区的内容。
* 对这个缓冲区的内容的改变将在新的缓冲区中可见;
* 然而,新的缓冲区本身将是只读的,并且不允许共享内容被破坏。
* 这两个缓冲区的位置、限制和标记值将是独立的。
*
* <p>
* 新缓冲区的容量、限制、位置和标记值与此缓冲区的相同。
*
* <p>
* 如果这个缓冲区本身是只读的,那么这个方法的行为方式与复制的方法完全相同。
* </p>
*
* @return The new, read-only byte buffer
*/
public abstract ByteBuffer asReadOnlyBuffer();
方法4个get,5个put
// -- Singleton get/put methods --
/**
* 相对的get方法。读取该缓冲区当前位置的字节,然后对位置进行增量。
*
* @return The byte at the buffer's current position
*
* @throws BufferUnderflowException If the buffer's current position is not
* smaller than its limit
*/
public abstract byte get();
/**
* 相对put方法(可选操作)。
*
* <p>
* 将给定的字节按当前位置写入该缓冲区,然后对位置进行递增。
* </p>
*
* @param b The byte to be written
*
* @return This buffer
*
* @throws BufferOverflowException If this buffer's current position is not
* smaller than its limit
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer put(byte b);
/**
* 绝对的get方法。读取给定索引处的字节。
*
* @param index The index from which the byte will be read
*
* @return The byte at the given index
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit
*/
public abstract byte get(int index);
/**
* 绝对put方法(可选操作)。
*
* <p>
* 将给定字节写入此缓冲区的给定索引处。
* </p>
*
* @param index The index at which the byte will be written
*
* @param b The byte value to be written
*
* @return This buffer
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer put(int index, byte b);
// -- Bulk get operations --
/**
* 相对批量获取方法。
*
* <p>
* 这个方法将字节从这个缓冲区传输到给定的目的数组中。
* 如果缓冲区中剩余的字节数少于满足请求所需的字节数,也就是说,
* 如果length> remaining(),则不传输字节数,并抛出BufferUnderflowException。
*
* <p>
* 否则,此方法将从缓冲区的当前位置和数组中的给定的offset处,将length字节从缓冲区复制到给定数组中。
* 然后,该缓冲区的位置按长度递增。
*
* <p>
* 换句话说,调用get(dst, off, len)与下面的循环具有完全相同的效果
*
* <pre>
* {@code
* for (int i = off; i < off + len; i++)
* dst[i] = src.get():
* }
* </pre>
*
* 除了它首先检查缓冲区中是否有足够的字节之外,它的效率可能要高得多。
*
* @param dst The array into which bytes are to be written
*
* @param offset The offset within the array of the first byte to be written;
* must be non-negative and no larger than <tt>dst.length</tt>
*
* @param length The maximum number of bytes to be written to the given array;
* must be non-negative and no larger than
* <tt>dst.length - offset</tt>
*
* @return This buffer
*
* @throws BufferUnderflowException If there are fewer than <tt>length</tt>
* bytes remaining in this buffer
*
* @throws IndexOutOfBoundsException If the preconditions on the <tt>offset</tt>
* and <tt>length</tt> parameters do not hold
*/
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;
}
/**
* 相对批量获取方法。
*
* <p>
* 这个方法将字节从这个缓冲区传输到给定的目的数组 中。
* src.get(a)方法的调用与调用的行为完全相同
*
* <pre>
* src.get(a, 0, a.length)
* </pre>
*
* @param dst The destination array
*
* @return This buffer
*
* @throws BufferUnderflowException If there are fewer than <tt>length</tt>
* bytes remaining in this buffer
*/
public ByteBuffer get(byte[] dst) {
return get(dst, 0, dst.length);
}
// -- Bulk put operations --
/**
* 相对大容量put方法(可选操作)。
*
* <p>
* 此方法将给定源缓冲区中剩余的字节传输到此缓冲区。
* 如果源缓冲区中剩余的字节比这个缓冲区中剩余的字节多,也就是说,
* 如果src.remaining() > remaining(),则没有字节被传输,并抛出一个BufferOverflowException。
*
* <p>
* 否则,此方法将n = src.remaining()字节从给定缓冲区复制到此缓冲区,从每个缓冲区的当前位置开始。
* 然后两个缓冲区的位置都增加n。
*
* <p>
* 换句话说,调用这种形式的dst.put(src)方法与循环具有完全相同的效果
*
* <pre>
* while (src.hasRemaining())
* dst.put(src.get());
* </pre>
*
* 除了它首先检查缓冲区中是否有足够的空间,而且它的效率可能更高。
*
* @param src The source buffer from which bytes are to be read; must not be
* this buffer
*
* @return This buffer
*
* @throws BufferOverflowException If there is insufficient space in this
* buffer for the remaining bytes in the source
* buffer
*
* @throws IllegalArgumentException If the source buffer is this buffer
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public ByteBuffer put(ByteBuffer src) {
if (src == this)
throw new IllegalArgumentException();
if (isReadOnly())
throw new ReadOnlyBufferException();
int n = src.remaining();
if (n > remaining())
throw new BufferOverflowException();
for (int i = 0; i < n; i++)
put(src.get());
return this;
}
/**
* 相对大容量put方法(可选操作)。
*
* <p>
* 此方法将给定源数组中的字节传输到此缓冲区中。
* 如果要从数组中复制的字节比该缓冲区中保留的字节多,也就是说,
* 如果length> remaining(),则不传输字节并抛出BufferOverflowException。
*
* <p>
* 否则,此方法将从数组中的给定偏移量和缓冲区的当前位置将length字节复制到该缓冲区中。
* 然后,该缓冲区的位置按长度递增。
*
* <p>
* 换句话说,调用这种形式的dst.put(src, off, len)与循环具有完全相同的效果
*
* <pre>
* {@code
* for (int i = off; i < off + len; i++)
* dst.put(a[i]);
* }
* </pre>
*
* 除了它首先检查缓冲区中是否有足够的空间,而且它的效率可能更高。
*
* @param src The array from which bytes are to be read
*
* @param offset The offset within the array of the first byte to be read; must
* be non-negative and no larger than <tt>array.length</tt>
*
* @param length The number of bytes to be read from the given array; must be
* non-negative and no larger than <tt>array.length - offset</tt>
*
* @return This buffer
*
* @throws BufferOverflowException If there is insufficient space in this
* buffer
*
* @throws IndexOutOfBoundsException If the preconditions on the <tt>offset</tt>
* and <tt>length</tt> parameters do not hold
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
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;
}
/**
* 相对大容量put方法(可选操作)。
*
* <p>
* 此方法将给定源字节数组的全部内容传输到此缓冲区。
* 调用这种形式的dst.put(a)方法的行为方式与调用完全相同
*
* <pre>
* dst.put(a, 0, a.length)
* </pre>
*
* @param src The source array
*
* @return This buffer
*
* @throws BufferOverflowException If there is insufficient space in this buffer
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public final ByteBuffer put(byte[] src) {
return put(src, 0, src.length);
}
方法array,arrayOffset,compact,isDirect,toString,hashCode,2个equals,compareTo
// -- Other stuff --
/**
* 告知此缓冲区是否由可访问的字节数组支持。
*
* <p>
* 如果此方法返回true,则可以安全地调用array和arrayOffset方法。
* </p>
*
* @return <tt>true</tt> if, and only if, this buffer is backed by an array and
* is not read-only
*/
public final boolean hasArray() {
// 不仅后备数组不能为null,而且不能为只读
return (hb != null) && !isReadOnly;
}
/**
* 返回返回此缓冲区的字节数组(可选操作)。
*
* <p>
* 对缓冲区内容的修改将导致返回数组的内容被修改,反之亦然。
*
* <p>
* 在调用这个方法之前调用hasArray方法,以确保这个缓冲区有一个可访问的后备数组。
* </p>
*
* @return 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;
}
/**
* 返回缓冲区的第一个元素在该缓冲区的后备数组中的偏移量(可选操作)。
*
* <p>
* 如果这个缓冲区是由一个数组支持的,那么缓冲区位置p相当于数组索引p + arrayOffset()。
*
* <p>
* 在调用这个方法之前调用hasArray方法,以确保这个缓冲区有一个可访问的后备数组。
* </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;
}
/**
* 压缩此缓冲区(可选操作)。
*
* <p>
* 缓冲区的当前位置和它的限制(如果有的话)之间的字节将被分配到缓冲区的开始部分。
* 即字节在p = position()被复制到索引0,p+1的字节被复制到索引1,直到limit()-1的字节被复制到n = limit() - 1 - p。
* position被设置到n+1,limit被设置到capacity。标记被抛弃
*
* <p>
* 缓冲区的位置被设置为复制的字节数,而不是为零,
* 以便在调用这个方法之后立即调用另一个相对的put方法。
* </p>
*
*
* <p>
* 在从缓冲区写入数据后调用此方法,以防写入未完成。
* 例如,下面的循环通过缓冲区buf将字节从一个通道复制到另一个通道:
*
* <blockquote>
*
* <pre>
* {@code
* buf.clear(); // Prepare buffer for use
* while (in.read(buf) >= 0 || buf.position != 0) {
* buf.flip();
* out.write(buf);
* buf.compact(); // In case of partial write
* }
* }
* </pre>
*
* </blockquote>
*
*
* @return This buffer
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer compact();
/**
* 告诉这个字节缓冲区是否直接。
*
* @return <tt>true</tt> if, and only if, this buffer is direct
*/
public abstract boolean isDirect();
/**
* 返回一个汇总此缓冲区状态的字符串。
*
* @return A summary string
*/
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();
}
/**
* 返回此缓冲区的当前哈希码。
*
* <p>
* 字节缓冲区的哈希码只依赖于它的剩余元素;
* 也就是说,在从position()到 并包括limit() - 1处的元素上。
*
* <p>
* 因为缓冲区哈希码是依赖于内容的,所以在哈希映射或类似的数据结构中使用缓冲区作为键是不明智的,除非知道它们的内容不会改变。
* </p>
*
* @return 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;
}
/**
* 告知此缓冲区是否等于另一个对象。
* <p>
* 两个字节的缓冲区是相等的,当且仅当,
* <ol>
* <li>
* <p>
* 它们有相同的元素类型,
* </p>
* </li>
* <li>
* <p>
* 它们有相同数量的剩余元素
* </p>
* </li>
* <li>
* <p>
* 剩下的两个元素序列,与它们的起始位置无关,是逐点相等的。
* </p>
* </li>
* </ol>
* <p>
* 字节缓冲区不等于任何其他类型的对象。
* </p>
*
* @param ob The object to which this buffer is to be compared
*
* @return <tt>true</tt> if, and only if, this buffer is equal to the given
* object
*/
public boolean equals(Object ob) {
if (this == ob)
return true;
if (!(ob instanceof ByteBuffer))
return false;
// 先把ob转为ByteBuffer
ByteBuffer that = (ByteBuffer) ob;
if (this.remaining() != that.remaining())
return false;
int p = this.position();
// 从双方的limit-1开始,到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;
}
/**
* 将这个缓冲区与另一个缓冲区进行比较。
*
* <p>
* 两个字节缓冲区的比较是通过字典方式比较它们的剩余元素序列,
* 而不考虑每个序列在其相应缓冲区中的起始位置。
* 通过调用Byte.compare(byte, byte)来比较字节元素对。
*
* <p>
* 字节缓冲区不能与任何其他类型的对象相比较。
*
* @return A negative integer, zero, or a positive integer as this buffer is
* less than, equal to, or greater than the given buffer
*/
public int compareTo(ByteBuffer that) {
int n = this.position() + Math.min(this.remaining(), that.remaining());
// 从position开始,逐个比较,如果都相同,最后比较剩余元素只差
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);
}
字段bigEndian,nativeByteOrder,方法order,_get,_put
// -- Other char stuff --
// -- Other byte stuff: Access to binary data --
boolean bigEndian // package-private
= true;
boolean nativeByteOrder // package-private
= (Bits.byteOrder() == ByteOrder.BIG_ENDIAN);
/**
* 检索该缓冲区的字节顺序。
*
* <p>
* 当读取或写入多字节值以及创建作为该字节缓冲区视图的缓冲区时,将使用字节顺序。
* 新创建的字节缓冲区的顺序总是BIG_ENDIAN。
* </p>
*
* @return This buffer's byte order
*/
public final ByteOrder order() {
return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
}
/**
* 修改这个缓冲区的字节顺序。
*
* @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
方法getXXX,putXXX,asXXXBuffer(char,short,int,long,float,double)
/**
* 读取字符值的相对get方法。
*
* <p>
* 读取缓冲区当前位置的下两个字节,根据当前字节顺序将它们组合成char值,然后将位置递增2。
* </p>
*
* @return The char value at the buffer's current position
*
* @throws BufferUnderflowException If there are fewer than two bytes remaining
* in this buffer
*/
public abstract char getChar();
/**
* 用于写入字符值的相对put方法(可选操作)。
*
* <p>
* 以当前字节顺序将包含给定char值的两个字节写入缓冲区的当前位置,然后将位置增加2。
* </p>
*
* @param value The char value to be written
*
* @return This buffer
*
* @throws BufferOverflowException If there are fewer than two bytes remaining
* in this buffer
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putChar(char value);
/**
* 读取字符值的绝对get方法。
*
* <p>
* 读取给定索引处的两个字节,并根据当前字节顺序将它们组合成char值。
* </p>
*
* @param index The index from which the bytes will be read
*
* @return The char value at the given index
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus one
*/
public abstract char getChar(int index);
/**
* 用于写入字符值的绝对put方法(可选操作)。
*
* <p>
* 按当前字节顺序将包含给定char值的两个字节写入到给定索引处的缓冲区中。
* </p>
*
* @param index The index at which the bytes will be written
*
* @param value The char value to be written
*
* @return This buffer
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus one
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putChar(int index, char value);
/**
* 将此字节缓冲区创建为char缓冲区的视图。
*
* <p>
* 新缓冲区的内容将从该缓冲区的当前位置开始。
* 对该缓冲区内容的更改将在新缓冲区中可见,反之亦然;
* 这两个缓冲区的位置、限制和标记值将是独立的。
*
* <p>
* 新缓冲区的位置将为零,其容量和限制将为该缓冲区中剩余的字节数除以2,其标记将未定义。
* 当且仅当此缓冲区是直接的,新缓冲区将是直接的;
* 当且仅当此缓冲区是只读的,它将是只读的。
* </p>
*
* @return A new char buffer
*/
public abstract CharBuffer asCharBuffer();
/**
* Relative <i>get</i> method for reading a short value.
*
* <p>
* Reads the next two bytes at this buffer's current position, composing them
* into a short value according to the current byte order, and then increments
* the position by two.
* </p>
*
* @return The short value at the buffer's current position
*
* @throws BufferUnderflowException If there are fewer than two bytes remaining
* in this buffer
*/
public abstract short getShort();
/**
* Relative <i>put</i> method for writing a short value <i>(optional
* operation)</i>.
*
* <p>
* Writes two bytes containing the given short value, in the current byte order,
* into this buffer at the current position, and then increments the position by
* two.
* </p>
*
* @param value The short value to be written
*
* @return This buffer
*
* @throws BufferOverflowException If there are fewer than two bytes remaining
* in this buffer
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putShort(short value);
/**
* Absolute <i>get</i> method for reading a short value.
*
* <p>
* Reads two bytes at the given index, composing them into a short value
* according to the current byte order.
* </p>
*
* @param index The index from which the bytes will be read
*
* @return The short value at the given index
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus one
*/
public abstract short getShort(int index);
/**
* Absolute <i>put</i> method for writing a short value <i>(optional
* operation)</i>.
*
* <p>
* Writes two bytes containing the given short 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 short value to be written
*
* @return This buffer
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus one
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putShort(int index, short value);
/**
* Creates a view of this byte buffer as a short 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 two, 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 short buffer
*/
public abstract ShortBuffer asShortBuffer();
/**
* 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();
/**
* Relative <i>get</i> method for reading a long value.
*
* <p>
* Reads the next eight bytes at this buffer's current position, composing them
* into a long value according to the current byte order, and then increments
* the position by eight.
* </p>
*
* @return The long value at the buffer's current position
*
* @throws BufferUnderflowException If there are fewer than eight bytes
* remaining in this buffer
*/
public abstract long getLong();
/**
* Relative <i>put</i> method for writing a long value <i>(optional
* operation)</i>.
*
* <p>
* Writes eight bytes containing the given long value, in the current byte
* order, into this buffer at the current position, and then increments the
* position by eight.
* </p>
*
* @param value The long value to be written
*
* @return This buffer
*
* @throws BufferOverflowException If there are fewer than eight bytes remaining
* in this buffer
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putLong(long value);
/**
* Absolute <i>get</i> method for reading a long value.
*
* <p>
* Reads eight bytes at the given index, composing them into a long value
* according to the current byte order.
* </p>
*
* @param index The index from which the bytes will be read
*
* @return The long value at the given index
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus
* seven
*/
public abstract long getLong(int index);
/**
* Absolute <i>put</i> method for writing a long value <i>(optional
* operation)</i>.
*
* <p>
* Writes eight bytes containing the given long 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 long value to be written
*
* @return This buffer
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus
* seven
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putLong(int index, long value);
/**
* Creates a view of this byte buffer as a long 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 eight, 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 long buffer
*/
public abstract LongBuffer asLongBuffer();
/**
* Relative <i>get</i> method for reading a float value.
*
* <p>
* Reads the next four bytes at this buffer's current position, composing them
* into a float value according to the current byte order, and then increments
* the position by four.
* </p>
*
* @return The float value at the buffer's current position
*
* @throws BufferUnderflowException If there are fewer than four bytes remaining
* in this buffer
*/
public abstract float getFloat();
/**
* Relative <i>put</i> method for writing a float value <i>(optional
* operation)</i>.
*
* <p>
* Writes four bytes containing the given float value, in the current byte
* order, into this buffer at the current position, and then increments the
* position by four.
* </p>
*
* @param value The float 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 putFloat(float value);
/**
* Absolute <i>get</i> method for reading a float value.
*
* <p>
* Reads four bytes at the given index, composing them into a float value
* according to the current byte order.
* </p>
*
* @param index The index from which the bytes will be read
*
* @return The float 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 float getFloat(int index);
/**
* Absolute <i>put</i> method for writing a float value <i>(optional
* operation)</i>.
*
* <p>
* Writes four bytes containing the given float 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 float 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 putFloat(int index, float value);
/**
* Creates a view of this byte buffer as a float 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 float buffer
*/
public abstract FloatBuffer asFloatBuffer();
/**
* Relative <i>get</i> method for reading a double value.
*
* <p>
* Reads the next eight bytes at this buffer's current position, composing them
* into a double value according to the current byte order, and then increments
* the position by eight.
* </p>
*
* @return The double value at the buffer's current position
*
* @throws BufferUnderflowException If there are fewer than eight bytes
* remaining in this buffer
*/
public abstract double getDouble();
/**
* Relative <i>put</i> method for writing a double value <i>(optional
* operation)</i>.
*
* <p>
* Writes eight bytes containing the given double value, in the current byte
* order, into this buffer at the current position, and then increments the
* position by eight.
* </p>
*
* @param value The double value to be written
*
* @return This buffer
*
* @throws BufferOverflowException If there are fewer than eight bytes remaining
* in this buffer
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putDouble(double value);
/**
* Absolute <i>get</i> method for reading a double value.
*
* <p>
* Reads eight bytes at the given index, composing them into a double value
* according to the current byte order.
* </p>
*
* @param index The index from which the bytes will be read
*
* @return The double value at the given index
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus
* seven
*/
public abstract double getDouble(int index);
/**
* Absolute <i>put</i> method for writing a double value <i>(optional
* operation)</i>.
*
* <p>
* Writes eight bytes containing the given double 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 double value to be written
*
* @return This buffer
*
* @throws IndexOutOfBoundsException If <tt>index</tt> is negative or not
* smaller than the buffer's limit, minus
* seven
*
* @throws ReadOnlyBufferException If this buffer is read-only
*/
public abstract ByteBuffer putDouble(int index, double value);
/**
* Creates a view of this byte buffer as a double 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 eight, 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 double buffer
*/
public abstract DoubleBuffer asDoubleBuffer();
本文地址:https://blog.csdn.net/xushiyu1996818/article/details/110184205
上一篇: 关胜在梁山是什么地位?他的实力如何