NIO学习 ByteBuffer详解

简介

本文主要记录Bytebuffer学习过程中笔记

数据结构

public abstract class ByteBuffer
    extends Buffer
    implements Comparable<ByteBuffer>
{

    // 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

public abstract class Buffer {

    /**
     * The characteristics of Spliterators that traverse and split elements
     * maintained in Buffers.
     */
    static final int SPLITERATOR_CHARACTERISTICS =
        Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;

    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;  //记录当前position的值。position被改变后,可以通过调用reset() 方法恢复到mark的位置。
    private int position = 0;  //下一个读写位置的索引(类似PC)。缓冲区的位置不能为负,并且不能大于limit
    private int limit; //缓冲区的界限。位于limit 后的数据不可读写。缓冲区的限制不能为负,并且不能大于其容量
    private int capacity; //缓冲区的容量。通过构造函数赋予,一旦设置,无法更改

    // Used only by direct buffers
    // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
    long address;

以上四个属性必须满足以下要求
mark <= position <= limit <= capacity

方法分析

在往Bytebuffer中读写数据时需要开启读写模式。经常需要进行读写切换,其实就是一个数组加上两个指针position和limit的变换。

put()方法

put()方法可以将一个数据放入到缓冲区中。进行该操作后,postition的值会+1,指向下一个可以放入的位置。capacity = limit ,为缓冲区容量的值。
在这里插入图片描述
测试一下,跟一下源码
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
首先判断一下当前position是否大于等于limit,是的话说明buffer数组已满,写不下了,抛出异常。
否则把position++之后,往buffer的position位置写入值。

![在这里插入图片描述](https://img-blog.csdnimg.cn/a559a047148f4df99b69ef50d2c094ff.png

flip()方法

flip()方法会切换对缓冲区的操作模式,由写->读
进行该操作后
写模式->读模式,position = 0 , limit 指向最后一个元素的下一个位置,capacity不变
在这里插入图片描述

public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

get()方法

get()方法会读取缓冲区中的一个值
进行该操作后,position会+1,如果超过了limit则会抛出异常
注意:get(i)方法不会改变position的值
在这里插入图片描述

public byte get() {
        return hb[ix(nextGetIndex())];
    }

rewind()方法

该方法只能在读模式下使用
rewind()方法后,会恢复position、limit和capacity的值,变为进行get()前的值
在这里插入图片描述

public final Buffer rewind() {
        position = 0;
        mark = -1;
        return this;
    }

clean()方法

clean()方法会将缓冲区中的各个属性恢复为最初的状态,通常用在读模式切换至写模式,position = 0, capacity = limit
此时缓冲区的数据依然存在,处于“被遗忘”状态,下次进行写操作时会覆盖这些数据
在这里插入图片描述

public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

在这里插入图片描述
debug下可以看到clean()后,buffer数组内容并没有清空,只是调整了两个指针,下次写的时候直接覆盖而言。

mark() 和 reset()方法

mark()方法会将postion的值保存到mark属性中
reset()方法会将position的值改为mark中保存的值
使用的场景就是如果你想要返回到之前的某一个位置上再进行一次读操作,可以在之前的那个位置进行一次mark(),读到后面的时候 调用reset(),就可以把指针设置成mark()时的值。

compact()方法

compact会把未读完的数据向前压缩,然后切换到写模式数据前移后,原位置的值并未清零,写时会覆盖之前的值。
在这里插入图片描述

public ByteBuffer compact() {
        //该方法把position指针后的未读的数据都拷贝一份赋值到buffer数组(从下标0开始覆盖)
        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
        position(remaining());
        limit(capacity());
        discardMark();
        return this;
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值