Buffer源码

这篇具有很好参考价值的文章主要介绍了Buffer源码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

介绍

首先 Buffer 是一个能存储基本数据类型的容器(除了 Boolean 类型),从 java.nio 包的继承结构就能看出来。

Buffer源码,源码,java

Java中的Buffer类是一个抽象类。Buffer类提供了一种将数据存储在内存中的方式,并提供了一些操作数据的方法。Buffer类可以存储不同类型的数据,并且可以方便地进行读取和写入操作。

常用的Buffer类有ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer和DoubleBuffer。这些Buffer类分别用于存储不同类型的数据,并且提供了相应的读写操作方法。

常量&变量

    /**
     * The characteristics of Spliterators that traverse and split elements
     * maintained in Buffers.
     * 在缓冲区中维护遍历和分割元素的拆分特征 TODO
     */
    static final int SPLITERATOR_CHARACTERISTICS =
        Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;

    // Invariants: mark <= position <= limit <= capacity
    /**
     * 一个新创建的 Buffer 具有以下几个性质:
     *
     * 它的 position 是 0;
     * mark 没有被定义(实际上是 -1);
     * 而 limit 值可能是 0,也可能是其他值,这取决于这个 Buffer 的类型;
     * Buffer 中每一个元素值都被初始化为 0
     */
    //当调用 reset() 方法被调用时,一个 Buffer 的 mark 值会被设定为当前的 position 值的大小。
    //如果mark=-1 ,会reset失败
    private int mark = -1;
    //它是下一个要读或者写的元素的索引,它是非负的且不会超过 limit 的大小。
    private int position = 0;
    //它是可以读或者写的最后一个元素的索引,它是非负的且不会超过 capacity 的大小。
    private int limit;
    //它表示一个 Buffer 包含的元素数量,它是非负且恒定不变的
    private int capacity;

    // Used only by direct buffers
    // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
    //这个属性只有在当前 Buffer 为 Direct Buffer 时才会使用
    long address;
  1. Capacity(容量):表示Buffer对象中可以存储的数据的最大数量。该值不能被更改。
  2. Position(位置):表示当前向Buffer对象中读取或写入数据的位置。
  3. Limit(限制):表示Buffer对象中可以读取或写入的数据的范围,即limit之后的数据不能读取或写入。
  4. Mark(标记):表示当前位置的一个备份,在调用reset()方法时,将回到该备份的位置。

构造方法

创建一个包含给定标记、位置、限制和容量的缓冲区。

    // Creates a new buffer with the given mark, position, limit, and capacity,
    // after checking invariants.
    //包内私有的构造器
    Buffer(int mark, int pos, int lim, int cap) {       // package-private
        //缓冲区容量小于0时抛出异常
        if (cap < 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);
        //根据传参设置缓冲区大小
        this.capacity = cap;
        //设置limit
        limit(lim);
        //设置position
        position(pos);
        if (mark >= 0) {
            if (mark > pos)
                //mark大于pos并且mark大于等于0时会抛出异常
                throw new IllegalArgumentException("mark > position: ("
                                                   + mark + " > " + pos + ")");
            //设置mark
            this.mark = mark;
        }
    }

常用方法

capacity

capacity()方法用于返回缓冲区的容量,即缓冲区中可以存储的元素的最大数量。

    /**
     * Returns this buffer's capacity.
     *
     * @return  The capacity of this buffer
     * 返回缓冲区容量
     */
    public final int capacity() {
        return capacity;
    }

position

用于获取缓冲区的当前位置。在缓冲区中,位置是指下一个要被读取或写入的元素的索引,初始位置为0。通过调用position()方法,可以获取当前位置,也可以将当前位置设置为指定值。

    /**
     * Returns this buffer's position.
     *
     * @return  The position of this buffer
     * 返回缓冲区下一次要读取或者写入的数组下标
     */
    public final int position() {
        return position;
    }

    /**
     * Sets this buffer's position.  If the mark is defined and larger than the
     * new position then it is discarded.
     *
     * @param  newPosition
     *         The new position value; must be non-negative
     *         and no larger than the current limit
     *
     * @return  This buffer
     *
     * @throws  IllegalArgumentException
     *          If the preconditions on <tt>newPosition</tt> do not hold
     *          设置缓冲区的游标
     */
    public final Buffer position(int newPosition) {
        //要设置的position值不能大于limit值或者小于0,否则就抛出异常。
        if ((newPosition > limit) || (newPosition < 0))
            throw createPositionException(newPosition);
        //如果设置的新的游标值比mark值小,就重置mark值为-1.
        if (mark > newPosition) mark = -1;
        //设置游标
        position = newPosition;
        return this;
    }

limit

用于设置缓冲区的限制(limit),调用limit方法后,缓冲区的限制将被设置为指定的值。如果缓冲区的当前位置大于新的限制值,则当前位置将被设置为新的限制值。

    /**
     * Returns this buffer's limit.
     *
     * @return  The limit of this buffer
     * 返回缓冲区的可用数据长度。
     */
    public final int limit() {
        return limit;
    }

    /**
     * Sets this buffer's limit.  If the position is larger than the new limit
     * then it is set to the new limit.  If the mark is defined and larger than
     * the new limit then it is discarded.
     *
     * @param  newLimit
     *         The new limit value; must be non-negative
     *         and no larger than this buffer's capacity
     *
     * @return  This buffer
     *
     * @throws  IllegalArgumentException
     *          If the preconditions on <tt>newLimit</tt> do not hold
     *           设置缓冲区的limit值,同时会保证position和mark值保证这几个值的关系符合规则。
     */
    public final Buffer limit(int newLimit) {
        //对要设置的新limit进行检查,如果大于缓冲区容量或者小于0就抛出异常
        if ((newLimit > capacity) || (newLimit < 0))
            throw new IllegalArgumentException();
        //设置limit
        limit = newLimit;
        //如果游标比可操作的最大数组下标还大的话,就把游标设置为limit
        if (position > newLimit) position = newLimit;
        //如果mark > limit,重置mark。
        if (mark > newLimit) mark = -1;
        return this;
    }

mark

mark方法会将一个标记设置在当前位置,以便在后续的操作中可以返回到这个位置。这个标记可以通过调用reset方法返回。

    /**
     * Sets this buffer's mark at its position.
     *
     * @return  This buffer
     * 标记当前position位置。
     */
    public final Buffer mark() {
        mark = position;
        return this;
    }

reset

用于重置缓冲区,即清空缓冲区并重新设置缓冲区的初始状态。



    /**
     * Resets this buffer's position to the previously-marked position.
     *
     * <p> Invoking this method neither changes nor discards the mark's
     * value. </p>
     *
     * @return  This buffer
     *
     * @throws  InvalidMarkException
     *          If the mark has not been set
     *          把游标恢复到标记的位置
     */
    public final Buffer reset() {
        int m = mark;
        //标记小于0时抛出异常
        if (m < 0)
            throw new InvalidMarkException();
        //重置游标至标记处
        position = m;
        return this;
    }

clear

用于重置缓冲区的位置、极限和标记。它将position设置为0,将标记设置为-1,并将极限设置为容量。此方法不会清除缓冲区中的数据。调用该方法后,您可以重新填充缓冲区或读取缓冲区中的现有数据。

    /**
     * Clears this buffer.  The position is set to zero, the limit is set to
     * the capacity, and the mark is discarded.
     *
     * <p> Invoke this method before using a sequence of channel-read or
     * <i>put</i> operations to fill this buffer.  For example:
     *
     * <blockquote><pre>
     * buf.clear();     // Prepare buffer for reading
     * in.read(buf);    // Read data</pre></blockquote>
     *
     * <p> This method does not actually erase the data in the buffer, but it
     * is named as if it did because it will most often be used in situations
     * in which that might as well be the case. </p>
     *
     * @return  This buffer
     * 清空缓冲区,其实就设置游标为0,limit设置回capacity值,mark重置,数据还是存在的。
     */
    public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

flip

flip方法是用于将写模式下的缓冲区切换为读模式。在写模式下,缓冲区的指针指向缓冲区的末尾,而在读模式下,指针指向缓冲区的开头。当需要读取已写入的数据时,需要使用flip方法切换模式。

    /**
     * Flips this buffer.  The limit is set to the current position and then
     * the position is set to zero.  If the mark is defined then it is
     * discarded.
     *
     * <p> After a sequence of channel-read or <i>put</i> operations, invoke
     * this method to prepare for a sequence of channel-write or relative
     * <i>get</i> operations.  For example:
     *
     * <blockquote><pre>
     * buf.put(magic);    // Prepend header
     * in.read(buf);      // Read data into rest of buffer
     * buf.flip();        // Flip buffer
     * out.write(buf);    // Write header + data to channel</pre></blockquote>
     *
     * <p> This method is often used in conjunction with the {@link
     * java.nio.ByteBuffer#compact compact} method when transferring data from
     * one place to another.  </p>
     *
     * @return  This buffer
     *  缓冲区创建时默认是写模式的,这个方法把缓冲区改为读模式。
     *  每次通过通道往存储设备中写数据都需要调用此方法把缓冲区设置为读模式。读取缓冲区的数据。
     */
    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

rewind

将缓冲区的position重置为0,表示可以重新读取缓冲区的内容。此方法不会改变缓冲区的limit和capacity。

    /**
     * Rewinds this buffer.  The position is set to zero and the mark is
     * discarded.
     *
     * <p> Invoke this method before a sequence of channel-write or <i>get</i>
     * operations, assuming that the limit has already been set
     * appropriately.  For example:
     *
     * <blockquote><pre>
     * out.write(buf);    // Write remaining data
     * buf.rewind();      // Rewind buffer
     * buf.get(array);    // Copy data into array</pre></blockquote>
     *
     * @return  This buffer
     * 重置游标,从新开始读、写数据。
     */
    public final Buffer rewind() {
        position = 0;
        mark = -1;
        return this;
    }

remaining

用于计算缓冲区中还剩余的未读元素数量。具体来说,remaining()方法返回值是一个int类型的整数,表示当前缓冲区中还有多少个元素可以被读取。

    /**
     * Returns the number of elements between the current position and the
     * limit.
     *
     * @return  The number of elements remaining in this buffer
     * 读模式下,返回剩余可读的数据长度,写模式下,返回剩余可写的缓冲区长度。
     */
    public final int remaining() {
        int rem = limit - position;
        return rem > 0 ? rem : 0;
    }

    /**
     * Tells whether there are any elements between the current position and
     * the limit.
     *
     * @return  <tt>true</tt> if, and only if, there is at least one element
     *          remaining in this buffer
     *          返回是否还有数据可读或者可写。
     */
    public final boolean hasRemaining() {
        return position < limit;
    }

nextGetIndex

用于获取下一个get(读取)操作的位置。读取操作和写入操作都是在当前位置(position)进行的。nextGetIndex方法返回的是当前位置加上1,即下一个读取操作应该从哪个位置开始读取数据。如果当前位置已经是buffer的limit值,那么下一个读取操作将无法进行,因为读取操作不能超过limit。

    /**
     * Checks the current position against the limit, throwing a {@link
     * BufferUnderflowException} if it is not smaller than the limit, and then
     * increments the position.
     *
     * @return  The current position value, before it is incremented
     * 读模式下游标往右移一位,也就是跳过一个数据。
     * 返回移动前的游标值。
     */
    final int nextGetIndex() {                          // package-private
        int p = position;
        //因为游标加一 所以要确保游标加一前要小于等于limit
        if (p >= limit)
            //当前游标>=limit抛出异常
            throw new BufferUnderflowException();
        position = p + 1;
        return p;
    }

    /**
     * 读模式下游标往右移动n位。
     * 返回移动前的游标
     * @param nb
     * @return
     */
    final int nextGetIndex(int nb) {                    // package-private
        int p = position;
        if (limit - p < nb)
            //判断加n后的游标是否大于limit,大于就抛出异常
            throw new BufferUnderflowException();
        position = p + nb;
        //返回移动前的游标。
        return p;
    }

nextPutIndex

用于返回下一个可写入的位置的索引。该方法会检查缓冲区的容量以确保缓冲区已分配足够的空间来写入数据。如果缓冲区容量不足,则会调用expand()方法来扩展缓冲区大小文章来源地址https://www.toymoban.com/news/detail-529548.html

    /**
     * Checks the current position against the limit, throwing a {@link
     * BufferOverflowException} if it is not smaller than the limit, and then
     * increments the position.
     *
     * @return  The current position value, before it is incremented
     * 写模式下游标往右移动1位。
     *  返回移动前的游标
     */
    final int nextPutIndex() {                          // package-private
        int p = position;
        if (p >= limit)
            throw new BufferOverflowException();
        position = p + 1;
        return p;
    }

    /**
     * 写模式下游标往右移动n位。
     *  返回移动前的游标
     * @param nb
     * @return
     */
    final int nextPutIndex(int nb) {                    // package-private
        int p = position;
        if (limit - p < nb)
            throw new BufferOverflowException();
        position = p + nb;
        return p;
    }

到了这里,关于Buffer源码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java中String类型的创建关系、什么是常量池、以及StringBuilder/Buffer等

    这段 Java 代码中,字符串 s1 和 s2 都使用字面量的方式赋值,它们在编译时会被放入常量池中。由于字符串常量池的特性,s1 和 s2 在常量池中的引用地址是相同的,因此 s1 == s2 的结果为 true。 而字符串 s3 和 s4 是通过 new 创建的,它们在内存中是两个不同的对象,因此

    2023年04月08日
    浏览(40)
  • java.net.SocketException: No buffer space available (maximum connections reached?): connect

            最近,有项目反馈调用第三方接口失败,查不到数据。现场用soapUI工具试了下,点执行按钮,一闪而过,接口没有任何返回值。一开始以为是第三方服务问题,后来查看日志,发现是自己的问题,报错如下:         Caused by: java.net.SocketException: No buffer space av

    2024年02月16日
    浏览(36)
  • ES启动报错:Caused by: java.net.SocketException: No buffer space available (maximum connections reached?)

    线上服务的es突然挂掉导致网站无法正常访问,看了下是es服务停止了,于是重启后出现了如下报错,对于报错信息的重点关注: Caused by: java.net.SocketException: No buffer space available (maximum connections reached?): connect 看报错信息是连接数太多,耗尽了某种资源。 查看当前所有的连接,

    2024年02月07日
    浏览(44)
  • 【MySQL】change buffer,buffer pool,redo log,bin log,undo log的作用

    当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InnoDB 会将这些更新操作缓存在 change buffer 中,这样就不需要从磁盘中读入这个数据页了。 在下次查询需要访问这个数据页的时候,将数据页

    2024年02月16日
    浏览(40)
  • Change Buffer详解

    change Buffer基本概念 Change Buffer:写缓冲区,是针对二级索引(辅助索引) 页的更新优化措施 作用: 在进行DML(写)操作(insert/update/delete)时,如果请求的是 辅助索引(非唯一键索引)没有在缓冲池 中时,并不会立刻将磁盘页加载到缓冲池,而是在Change Buffer记录缓冲变更,等未来数据

    2024年02月02日
    浏览(35)
  • MySQL - Buffer Pool

    Buffer Pool 主要用于缓存数据库表的数据页,以提高数据库的读取性能: 缓存数据页 :Buffer Pool 是 MySQL 中用于缓存数据页的内存区域。数据页通常包含数据库表的数据,如行记录等。当查询或读取数据时,MySQL会首先查看Buffer Pool中是否已经缓存了相应的数据页。如果数据页在

    2024年02月07日
    浏览(38)
  • Buffer(缓冲)、Cache(缓存)

    Buffer 用途:缓冲通常用于临时存储数据,以平衡不同速度的数据传输过程直接的差异。它可以用来解决数据传输速度不匹配的问题。 例如: 当您在观看视频时,视频播放器会缓冲一段时间的视频数据,以便在网络速度慢或不稳定的情况下也能够流畅的播放 用完之后,就清除

    2024年02月03日
    浏览(48)
  • 04-Buffer的使用

    Buffer和二进制 对于前端开发来说,通常很少会和二进制打交道,但是对于服务器端为了做很多的功能,我们必须直接去操作其二进制的数据;所以Node为了可以方便开发者完成更多功能,提供给了我们一个类Buffer,并且它是全局的。 1.Buffer中存储的是二进制数据,那么到底是

    2024年02月10日
    浏览(28)
  • Node.js:Buffer基础

    在Node.js中,Buffer类是用于处理二进制数据的实用工具。它是一个全局对象,可以在所有模块中访问,而无需使用 require 引入。 更多请查看Node.js中文文档 可以使用以下方法之一来创建一个新的Buffer对象: 使用字符串创建: 使用数组创建: 使用Buffer.alloc创建指定大小的Buffe

    2024年02月09日
    浏览(38)
  • MySQL中的Buffer Pool

            Buffer Pool是数据库的一个内存组件,里面缓存了磁盘上的真实数据,然后我们的Java系统对数据库执行的增删改操作,其实主要就是对这个内存数据结构中的缓存数据执行的。我们先来看一下下面的图,里面就画了数据库中的Buffer Pool内存组件。         接着我

    2024年02月11日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包