JDK源码阅读(3):AbstractStringBuilder、StringBuffer、StringBuilder类阅读笔记
AbstractStringBuilder
abstract class AbstractStringBuilder implements Appendable, CharSequence{
...
}
1. inflate方法
inflate()方法可以将当前的Latin1编码的字符串膨胀到16位,即UTF16编码(Latin1编码为8位)
/**
* If the coder is "isLatin1", this inflates the internal 8-bit storage
* to 16-bit <hi=0, low> pair storage.
*/
private void inflate() {
if (!isLatin1()) {
return;
}
byte[] buf = StringUTF16.newBytesFor(value.length);
StringLatin1.inflate(value, 0, buf, 0, count);
this.value = buf;
this.coder = UTF16;
}
2. ensureCapacity方法
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0) {
ensureCapacityInternal(minimumCapacity);
}
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
if (minimumCapacity - oldCapacity > 0) {
// 拷贝过去
value = Arrays.copyOf(value, newCapacity(minimumCapacity) << coder);
}
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
int newCapacity = (oldCapacity << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
ensureCapacity(miniCapacity)方法保证当前容器的大小不小于miniCapacity,如果小于的话就要进行扩容处理。扩容成下面两者中的较大值。
- miniCapacity
- 2*oldCapacity
3. setCharAt方法
setCharAt()方法可以将index处的字符设为ch
public void setCharAt(int index, char ch) {
checkIndex(index, count);
if (isLatin1() && StringLatin1.canEncode(ch)) {
value[index] = (byte)ch;
} else {
if (isLatin1()) {
inflate();
}
StringUTF16.putCharSB(value, index, ch);
}
}
4. append方法
append()方法根据参数类型不同,在字符串后面追加。
public AbstractStringBuilder append(CharSequence s) {
if (s == null) {
return appendNull();
}
if (s instanceof String) {
return this.append((String)s);
}
if (s instanceof AbstractStringBuilder) {
return this.append((AbstractStringBuilder)s);
}
return this.append(s, 0, s.length());
}
值得一提的是这个appendNull()方法,当我们在试图append一个空对象时,它居然选择在builder串后面加上一个“null”,看下面的示例。
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("a");
String s = null;
stringBuilder.append(s);
System.out.println(stringBuilder.toString());
System.out.println(stringBuilder.toString().length());
}
输出结果居然是
anull
5
也就是说,当append空对象时,会append一个“null”字符串。
另外,当我们尝试append一个boolean对象时,会append一个“true”串或者“false”串。
5. delete方法
delete方法删除builder中的一段
public AbstractStringBuilder delete(int start, int end) {
int count = this.count;
if (end > count) {
end = count;
}
checkRangeSIOOBE(start, end, count);
int len = end - start;
if (len > 0) {
shift(end, -len);
this.count = count - len;
}
return this;
}
类似地还有deleteCharAt
public AbstractStringBuilder deleteCharAt(int index) {
checkIndex(index, count);
shift(index + 1, -1);
count--;
return this;
}
6. reverse方法
reverse()方法可以逆转字符的顺序。
public AbstractStringBuilder reverse() {
byte[] val = this.value;
int count = this.count;
int coder = this.coder;
int n = count - 1;
if (COMPACT_STRINGS && coder == LATIN1) {
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
byte cj = val[j];
val[j] = val[k];
val[k] = cj;
}
} else {
StringUTF16.reverse(val, count);
}
return this;
}
实际的方法就是双指针靠拢+交换、
StringBuffer
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
{
StringBuffer类几乎所有方法都是通过super关键字调用AbstractStringBuilder父类的方法。
StringBuffer实现同步的方式就是给所有方法加上synchronized关键字。
1. toStringCache变量
/**
* A cache of the last value returned by toString. Cleared
* whenever the StringBuffer is modified.
*/
private transient String toStringCache;
toStringCache缓存了toString()方法的最后一次调用的值,在每次StringBuffer被修改前这个缓存会清除。
toString()方法中检查如果有缓存,就直接返回缓存。这样不用每次都处理toString()的过程,而只在需要的时候处理。
public synchronized String toString() {
if (toStringCache == null) {
return toStringCache =
isLatin1() ? StringLatin1.newString(value, 0, count)
: StringUTF16.newString(value, 0, count);
}
return new String(toStringCache);
}
StringBuilder
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{
...
}
StringBuilder类几乎所有方法都是通过super关键字调用AbstractStringBuilder父类的方法。
JDK源码阅读(3):AbstractStringBuilder、StringBuffer、StringBuilder类阅读笔记的更多相关文章
- Java1.8 JDK源码中,对两个类进行 按位与 操作是什么意思
Java容器类库中的Map接口(java\util\Map.java)中有一个Entry接口(java\util\Map.java),其中有几个接口方法用到了类和类的按位与操作,即类和类之间有 &am ...
- JDK源码阅读顺序
很多java开发的小伙伴都会阅读jdk源码,然而确不知道应该从哪读起.以下为小编整理的通常所需阅读的源码范围. 标题为包名,后面序号为优先级1-4,优先级递减 1.java.lang 1) Obj ...
- JDK源码学习系列03----StringBuffer+StringBuilder
JDK源码学习系列03----StringBuffer+StringBuilder 由于前面学习了StringBuffer和StringBuilder的父类A ...
- 如何阅读JDK源码
JDK源码阅读笔记: https://github.com/kangjianwei/LearningJDK 如何阅读源码,是每个程序员需要面临的一项挑战. 为什么需要阅读源码?从实用性的角度来看,主要 ...
- 如何有效的阅读JDK源码
阅读Java源码的前提条件: 1.技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持. 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃<Core Java>,那样 ...
- 利用IDEA搭建JDK源码阅读环境
利用IDEA搭建JDK源码阅读环境 首先新建一个java基础项目 基础目录 source 源码 test 测试源码和入口 准备JDK源码 下图框起来的路径就是jdk的储存位置 打开jdk目录,找到sr ...
- jdk源码阅读笔记-HashSet
通过阅读源码发现,HashSet底层的实现源码其实就是调用HashMap的方法实现的,所以如果你阅读过HashMap或对HashMap比较熟悉的话,那么阅读HashSet就很轻松,也很容易理解了.我之 ...
- 如何阅读jdk源码?
简介 这篇文章主要讲述jdk本身的源码该如何阅读,关于各种框架的源码阅读我们后面再一起探讨. 笔者认为阅读源码主要包括下面几个步骤. 设定目标 凡事皆有目的,阅读源码也是一样. 从大的方面来说,我们阅 ...
- JDK源码阅读(三):ArraryList源码解析
今天来看一下ArrayList的源码 目录 介绍 继承结构 属性 构造方法 add方法 remove方法 修改方法 获取元素 size()方法 isEmpty方法 clear方法 循环数组 1.介绍 ...
- JDK源码阅读(一):Object源码分析
最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 has ...
随机推荐
- Python的GPU编程实例——近邻表计算
技术背景 GPU加速是现代工业各种场景中非常常用的一种技术,这得益于GPU计算的高度并行化.在Python中存在有多种GPU并行优化的解决方案,包括之前的博客中提到的cupy.pycuda和numba ...
- 轻松搞定webpack5.x
源码地址:https://gitee.com/cyp926/webpack-project.git "webpack": "^5.46.0", "we ...
- C# - 习题04_分析代码写出结果i1、i2、c.i、str、c.str
时间:2017-08-23 整理:byzqy 题目:分析如下代码,写出程序输出结果. 文件:Class1.cs using System; namespace Interview3 { class C ...
- 备忘:Linux内核编程的几个注意事项
虚拟地址转物理地址要用__pa 内核程序创建的一段地址连续的共享内存,通过内存映射可以让用户态进程存取.之前在RHEL/CentOS的x86_64架构上工作正常.后来在aarch64架构的银河麒麟(L ...
- 高并发HHTP实践
当今,正处于互联网高速发展的时代,每个人的生活都离不开互联网,互联网已经影响了每个人生活的方方面面.我们使用淘宝.京东进行购物,使用微信进行沟通,使用美图秀秀进行拍照美化等等.而这些每一步的操作下面, ...
- MongoDB 常见问题 - 解决 brew services list 查看 MongoDB 服务 status 显示 error 的问题
问题背景 将 MongoDB 作为服务运行 brew services start mongodb-community@4.4 也显示运行成功了,但是查看服务列表的时候,发现 MongoDB 服务的还 ...
- python3 spider [ urllib.request ]
# # 导入urllib库的urlopen函数 # from urllib.request import urlopen # # 发出请求,获取html # html = urlopen(" ...
- 硕盟type-c转接头HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞
硕盟SM-T54是一款 TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显 ...
- Spring5(五)——AOP
一.AOP 1.介绍 AOP(Aspect Oriented Programming),面向切面编程.它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共 ...
- idea鼠标双击.log日志文件无法打开
发现只要再mybatis-config.xml的起别名中加<package name="xxx"/>,就会导致Reader entry: ���� 1 n乱码,而R ...