当前位置:网站首页>ByteArrayOutputStream 类源码分析
ByteArrayOutputStream 类源码分析
2022-07-29 15:35:00 【51CTO】
这是 《水煮 JDK 源码》系列 的第2篇文章,计划撰写100篇关于JDK源码相关的文章
ByteArrayOutputStream 类位于 java.io 包下,继承于 OutputStream 类,从字面上可以看出,它表示的是一个字节数组输出流。它的实现方式是先在内存中创建一个字节数组缓冲区 byte buf[],然后把所有发送到输出流的数据保存于字节数组缓冲区中,其中字节数组缓冲区会随着数据的增加而自动调整大小,其UML 类图如下:

1、构造函数
ByteArrayOutputStream 类提供两个构造方法,分别如下:
无参构造方法默认创建一个32字节的缓冲区,而另一个构造方法则是创建指定大小为 size 的缓冲区。
ByteArrayOutputStream 类中有3个成员变量 buf[] 、 count 和 MAX_ARRAY_SIZE,其定义如下:
在成功创建字节数组输出流后,就可以调用相应的方法进行操作,操作方法主要分为下面几类:
写入字节数据方法
字节数组扩容方法
将字节数组转换为字符串方法
其他方法
2、写入字节数据方法
ByteArrayOutputStream 提供了2个写入方法,1个写入到其他输出流方法,分别如下:
public synchronized void write(int b):将指定的字节写入字节数组输出流;public synchronized void write(byte b[], int off, int len):将指定字节数组中从偏移量 off 开始的 len长度的字节写入字节数组输出流中public synchronized void writeTo(OutputStream out) throws IOException:将字节数组输出流中的全部数据写入到输出流参数中,调用的是OutputStream的write()方法
这3个写入方法都使用 synchronized 关键字,即为同步方法。
在向字节数组中写入新数据时,首先要做的就是检查当前数组的容量,如果容量不足,则需要先对数组进行扩容,然后再保存数据;如果同时写入多个字节数据,将会使用 System.arraycopy() 方法进行数组拷贝,它是一个 native 方法,其定义如下:
3、字节数组扩容方法
ByteArrayOutputStream 可以实现自动对字节数组进行扩容,当数组大小无法存放新的字节内容时,就会自动进行扩容,数组的扩容主要涉及到下面的三个方法:
private void ensureCapacity(int minCapacity):检查字节数组容量大小private void grow(int minCapacity):字节数组扩容private static int hugeCapacity(int minCapacity):检查是否超过最大容量,最大容量为Integer.MAX_VALUE - 8
在 write() 方法中可以看到,当向字节数组中写入数据时,会先调用 ensureCapacity() 方法检查数组的容量,如果容量不足,则会进行扩容,其实现如下:
在对数据进行扩容操作时,默认的扩容策略是直接将数组大小增加1倍,如果扩容后仍然不够,则等于所需最小容量大小,然后在与数组最大值进行比较,判断扩容后的数组是否超过允许的最大值。
数据扩容时,调用的是 Arrays.copyOf() ,该方法是位于 java.util 包下 Arrays 类的方法, 其定义如下:
Arrays.copyOf()方法的实现方式是先创建一个长度为 newLength 的新字节数组,然后使用 System.arraycopy() 方法进行数组数据的拷贝,最后返回新的数组,也就是说 ByteArrayOutputStream 进行数组扩容时,都会执行数据拷贝的动作。
4、将字节数组转换为字符串方法
ByteArrayOutputStream 提供了3个将字节数组转换为字符串的方法,其中有1个已经被废弃,具体如下:
public synchronized String toString():根据默认字符编码将缓冲区的字节内容转换为字符串public synchronized String toString(String charsetName):根据指定字符编码将缓冲区的字节内容转换为字符串public synchronized String toString(int hibyte):该方法已废弃
3个 toString() 方法都是使用了关键词 synchronized,即为同步方法。
将字节数组转换为字符串的实现都比较简单,都是直接 new String() 创建一个新的字符串,在转换的时候可以使用系统默认的字符编码,也可以使用指定的字符编码,关于上面两个 new String() 方法实现如下:
关于系统默认的字符编码格式获取方法为:Charset.defaultCharset().name(),其具体实现如下:
从上面的实现可以看出,如果默认编码不存在,则使用 UTF-8 编码格式。
5、其他方法
ByteArrayOutputStream 提供的其他方法主要有以下这些:
public synchronized void reset():将字节数组输出流的count字段重新置为0,丢弃所有已累积的数据输出;public synchronized byte toByteArray()[]:拷贝并创建一个新的字节数组,数组大小和内容与当前输出流一致;public synchronized int size():获取字节数组的大小;public void close() throws IOException:关闭字节数组输出流
下面分别看看这些方法的具体实现。
需要注意的是 ByteArrayOutputStream 的 close() 方法没有任何实现,即使调用该方法,也没有任何作用。
边栏推荐
猜你喜欢
随机推荐
蚂蚁三面滑铁卢!遭分布式截胡,靠这些笔记潜修 30 天,挺进京东
CAN报文:数据帧详解
公司官网建站笔记(六):域名进行公安备案并将备案号显示在网页底部
ES6 from entry to master # 10: Set the Set data type
网络知识大集合(最详细)与网络通信过程
奇怪,为什么ArrayList初始化容量大小为10?
I/O Code Practice
边缘计算如何与小程序结合?智能家居如何借势发展?
SAP ABAP OData 服务诊断工具 /IWFND/ERROR_LOG 的使用方法试读版
你真的了解Redis的持久化机制吗?
图文结合纯c手写内存池
基于全志D1-H和XR806的名贵植物监控装置
Impala时间函数总结
R语言中给数据框增加分组/根据样本名称添加分组的代码
货比三家 tb1.3
Shell script programming - operation
Unable to open the source file in qt vs2015 "QtWidgets" solution
如何在CentOS 8上安装PHP
中国大学慕课mooc答题/自动播放脚本(domooc)使用教程
cmake(14):利用set_property命令设置全局属性



![[Designers must learn] Lighting skills of Enscape in SketchUp](/img/98/0b4e5241774f03141ef1c918707d86.jpg)


![[MySQL] 排序与分页](/img/39/2437714e6d154c3c98c6ccdad06d32.png)


