[源码分析]AbstractStringBuilder

Java中, AbstractStringBuilder是 StringBuilder 和 StringBuffer 的父类. 所以了解StringBuilder和StringBuffer前, 有必要先了解一下这个抽象父类.

这里附上另外两篇文章的连接:

StringBuilder : http://www.cnblogs.com/noKing/p/jdk8_StringBuilder.html

StringBuffer : http://www.cnblogs.com/noKing/p/9431618.html

value字段

在这里存储字符串内容

构造器

在构造器内立即创建一个capacity大小的数组, 作为value字段的值.

扩容

每次插入类的操作都会确保空间大小足够. 如果不够就会扩容, 再插入.

扩容是靠调用这个方法, 来确保每次有足够的空间.

也就是说扩容后具体是多大, 还要根据newCapacity这个方法来定:

可以看到, 扩容策略是原先的数组长度乘以2, 然后加2.

如果oldLength*2+2 之后的大小足够大了, 那么下次的数组大小就是这个数值了.

但是oldLength*2+2之后的大小还是不够, 那么就直接采用传进来的数据作为目标大小.(先不讨论hugeCapacity)

trimToSize

trimToSize的使用结果如下:

public class AbstractStringBuilderTest {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("hello");
System.out.println("size:" + sb.length()); // 5
System.out.println("capacity" + sb.capacity()); // 16
sb.trimToSize();
System.out.println("size:" + sb.length()); // 5
System.out.println("capacity" + sb.capacity()); // 5
}
}

setLength方法

详细注意事项用下面的例子来说明:

public class AbstractStringBuilderTest {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("hello");
System.out.println(sb.toString()); // hello
System.out.println("size:" + sb.length()); // 5
System.out.println("capacity" + sb.capacity()); // 16
sb.setLength(2);
System.out.println(sb.toString()); // he
System.out.println("size:" + sb.length()); // 2
System.out.println("capacity" + sb.capacity()); // 16
sb.setLength(20);
System.out.println(sb.toString()); // he\0\0\0\00\0\0\00\0\0\00\0\0\0\0\0
System.out.println("size:" + sb.length()); // 20
System.out.println("capacity" + sb.capacity()); // 34
sb.setLength(77);
System.out.println("size:" + sb.length()); // 77
System.out.println("capacity" + sb.capacity()); // 77
}
}

在上面这个demo中, 我用到了三次setLength. 但是每次调用后的结果都多多少少有些区别.

第1次调用: 因为setLength的参数比当前字符串的长度要小, 所以字符串被截短了, 长度也直接变为了相应的数值.

第2次调用: 因为setLength的参数比当前字符串的长度要大, 所以多余出来的部分用'\0'来补充.length是20. 而数组进行一次扩容就可以hold住20这个大小, 所以就进行一次正常的扩容就行了. 正常的扩容就是原来的长度乘以2, 然后再加2, 所以是34.

第三次调用: 当前数组的长度是34, 而我setLength的参数是77.  34进行一次扩容才只是34*2+2 = 70. 因为77大于这个70, 所以capacity也就是77了.

同样是参数大于当前数组的大小, 同样是用'\0'来补充. 但是如果这个参数太大, 以至于一次扩容无法hold住这个大小, 那么capacity就会直接设置为那个数值.

这段逻辑在newCapacity方法中. 代码前面将扩容的时候粘贴过了.

charAt方法

我们可以看到charAt就是判断数组越界, 来抛出异常.

返回值直接就是用的数组的下角标.

根据这个, setCharAt方法就不用多说了, 也是判断是否越界, 然后给数组的相应位置赋值.

append方法

append方法的很多重载就是靠调用getChars方法来达到尾插的目的的. 很简单, 就不提了.

就是appendNull方法, 很想吐槽...看完了眼前一亮....

嗯...还有append方法的bool型重载:

.....

substring

可以看到substring底层是直接调用的new String

reverse方法

两个指针j和k. 关于中心对称. 从中间开始一边向两边遍历, 一边交换. 就完成了翻转.

总结

这个类没什么特别的, 但还是稍微总结一下

1. 构造器里立即初始化数组

2. 扩容方式为 扩容前长度 * 2 + 2

3. 当前第2条说的不严谨. 首先想想为什么扩容呢? 因为插入一个字符串的时候, 剩余空间不足了, 所以扩容. 如果插入的这个字符串太长, 导致扩容一次也无法容纳下呢? 那么就直接把长度设置为 扩容前长度+ 插入的字符串长度 .

4. 大规模使用了System.arraycopy方法.

[源码分析]AbstractStringBuilder的更多相关文章

  1. [源码]String StringBuffer StringBudlider(2)StringBuffer StringBuilder源码分析

      纵骑横飞 章仕烜   昨天比较忙 今天把StringBuffer StringBulider的源码分析 献上   在讲 StringBuffer StringBuilder 之前 ,我们先看一下 ...

  2. String、StringBuffer、StringBuilder源码分析

    利用反编译具体看看"+"的过程 1 public class Test 2 { 3 public static void main(String[] args) 4 { 5 int ...

  3. [源码分析]StringBuilder

    [源码分析]StringBuilder StringBuilder是继承自AbstractStringBuilder的. 这里附上另外两篇文章的连接: AbstractStringBuilder :  ...

  4. [源码分析]StringBuffer

    [源码分析]StringBuffer StringBuffer是继承自AbstractStringBuilder的. 这里附上另外两篇文章的连接: AbstractStringBuilder : ht ...

  5. String,StringBuffer,StringBuilder源码分析

    1.类结构 String Diagrams StringBuffer Diagrams StringBuilder Diagrams 通过以上Diagrams可以看出,String,StringBuf ...

  6. String 类源码分析

    String 源码分析 String 类代表字符序列,Java 中所有的字符串字面量都作为此类的实例. String 对象是不可变的,它们的值在创建之后就不能改变,因此 String 是线程安全的. ...

  7. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  8. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  9. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

随机推荐

  1. 配置用户Log on as service

    Logon to the computer with administrative privileges. Open the ‘Administrative Tools’ and open the ‘ ...

  2. Web前端教程-HTML及标签的使用

    目录 1. HTML简介 1.1. HTML文档基本结构 2. 标签 2.1. 标签语法 1.2. 标签的属性和值 1.3. 常见的标签 1. 基础标签 2. 格式标签 3. 表单标签 4. 框架标签 ...

  3. vps install ss

    1.install ss yum install python-setuptools easy_install pip pip install shadowsocks 2.config ss (sin ...

  4. js 发送短信倒计时、秒杀倒计时实现代码

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  5. JAVA进阶23

    1.统计文件夹大小 package cn.demo02; import java.io.File; /** * @Classname DirTest03 * @Description TODO * @ ...

  6. Linux Docker的部署

    1.安装 $ yum -y install docker 2.启动docker服务 $ systemctl start docker 3.设置开启自启 $ systemctl enable docke ...

  7. .NET、PHP、MySql、JS中的时间戳你每次是手写还是复制?这篇文章让你一次性搞懂

    什么是时间戳(chuō)? 答:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数. 为什么时间戳要从1970年01月0 ...

  8. 使用 canvas 画图时图像文字模糊的解决办法

    最近在使用 canvas 画图的时候,遇到了图像文字模糊的问题,解决思路就是根据分辨率创建不同尺寸的画布.以下是创建高分辨率画布的代码: /** * 创建高分辨率画布 * @param w 画布宽 * ...

  9. 发布时一键添加html中的css标签和script标签版本号来防止浏览器缓存

    AppendFileVersion 是一个VSIX插件支持vs2015意以上版本 是我用来发布时一键添加html中的css标签和script标签版本号来防止浏览器缓存 分享给大家! download ...

  10. 01构建第一个SpringBoot工程

    第一篇:构建第一个SpringBoot工程 文章指导 学习笔记 学习代码 创建项目 创建工程:Idea-> new Project ->Spring Initializr ->填写g ...