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 ...
随机推荐
- linux 端口80占用问题
主要是搭建一次ghost博客网站改成80端口无法启动提示被占用. 提示:80端口被占用,启动失败. netstat -ano 或者 netstat -apn | grep 80 没有发现占用80端口的 ...
- tomcat Debug 启动
eclipse有web工程,将打包为war包(export -> War file) 将打包好的war 包放在tomcat 的webapps下面: 配置debug: 参考来自 http://bl ...
- Struts2常见问题
时间:2017-1-14 21:29 1.配置Struts2过滤器之后无法正常访问Servlet 自己手动配置过滤器,参数为要访问的Servlet
- 2020最精细的Java学习路线图
在吾爱破解发布的Java学习路线图自我感觉良好,之后看到动力节点Java学院的这份学习路线图感觉专业的东西还得专业的人来做,这份专业的学路线图把我上次的Java学习路线图秒成渣,虽然内容差不多,上份是 ...
- vue3 项目 用 vue-video-player 做直播 ( 亲测可用 )
npm 安装 npm install --save vue-video-player npm install --save videojs-flash 1 <template> 2 < ...
- 这款打怪升级的小游戏,7 年前出生于 GitHub 社区,如今在谷歌商店有 8 万人打了满分
今天我在 GitHub 摸鱼寻找新的"目标"时,发现了一个开源项目是 RougeLike 类的角色扮演游戏「破碎版像素地牢」(Shattered Pixel Dungeon)类似魔 ...
- 如何让阿三 Windows 10、11 的恢复分区(Recovery Partition)恢复到 “盖茨” 模式
如何将 Windows Server 2022 的恢复分区(Recovery Partition)移动到 C 盘之前,恢复 C 盘容量调整功能. 请访问原文链接:https://sysin.org/b ...
- python库--flashtext--大规模数据清洗利器
flashtext.keyword (flashtext) 类/方法 返回值 参数 说明 .KeywordProcessor() 对象kp case_sensitive=False 是否区分大小写 添 ...
- 常见shell脚本测试题 for/while语句
1.计算从1到100所有整数的和2.提示用户输入一个小于100的整数,并计算从1到该数之间所有整数的和3.求从1到100所有整数的偶数和.奇数和4.执行脚本输入用户名,若该用户存在,输出提示该用户已存 ...
- IO流实现简单的文件的剪切
思路: 判断 即将 复制的文件是文件夹还是文件 遍历需要复制的源文件夹 如果是文件夹,就通过流创建一个同样的子文件夹 如果是文件,就复制过去 接下来上代码 public class Demo1 { p ...