java nio ByteBuffer源码分析

本文详细剖析了Java NIO中的ByteBuffer类,涵盖了其关键字段如hb, offset, isReadOnly及构造函数。深入讲解了allocateDirect、allocate、wrap等方法,以及get和put系列方法的实现。同时,还探讨了order方法、bigEndian和nativeByteOrder字段,以及getXXX和putXXX方法,为理解ByteBuffer的内部工作原理提供了全面的指导。" 112621699,10535966,3轴VS3+2轴VS5轴联动:数控加工的区别解析,"['数控技术', '机械制造', '工业自动化', '机床', '加工工艺']
摘要由CSDN通过智能技术生成

目录

简介

字段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,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 a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值