JDK源码阅读之AbstractStringBuilder类

2023-11-17

AbstractStringBuilder类的作用

AbstractStringBuilder是一个抽象类,也是StringBuilder和StringBuffer类的父类,这个类是这两个类的共同点的体现。

AbstractStringBuilder类的类图

AbstractStringBuilder类图
从类图中可以看出,

  1. 该类实现了Appendable接口,它的实现类的对象能够被添加 char 序列和值。如果某个类的实例打算接收取自 java.util.Formatter 的格式化输出,那么该类必须实现 Appendable 接口。
  2. 该类实现了CharSequence接口,CharSequence 是 char 值的一个可读序列。此接口对许多不同种类的 char 序列提供统一的只读访问

AbstractStringBuilder类的重点方法

属性变量

	/**
     * The value is used for character storage.
     */
    char[] value;

    /**
     * The count is the number of characters used.
     */
    int count;

构造方法

    /**
     * This no-arg constructor is necessary for serialization of subclasses.
     */
    AbstractStringBuilder() {
    }

    /**
     * Creates an AbstractStringBuilder of the specified capacity.
     */
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

构造方法也是非常简单,不过这里有个容易混淆的变量,capacity代表的容量,length代表的是长度,这两个变量是不同的。

精华方法

public void ensureCapacity(int minimumCapacity)

   // 确保容量大小
    public void ensureCapacity(int minimumCapacity) {
    	// 如果minimumCapacity 大于0,就开始内部确认容量
        if (minimumCapacity > 0)
            ensureCapacityInternal(minimumCapacity);
    }
	// 内部确认容量
	private void ensureCapacityInternal(int minimumCapacity) {
        // 如果minimumCapacity  > value.length ,那么确定扩容
        if (minimumCapacity - value.length > 0)
            expandCapacity(minimumCapacity);
    }
	// 扩容方法
	void expandCapacity(int minimumCapacity) {
		// 将容量扩大到原来的2倍+2
        int newCapacity = value.length * 2 + 2;
        //如果扩大后没有达到需要的容量,将需要的容量设定为容量值
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        // 将数组扩大,完成扩容
        value = Arrays.copyOf(value, newCapacity);
    }

从源码中分析可以得知:他采取的扩容策略是:length*2+2,如果没有达到要求,会将需要的容量设置为容量值。
个人认为:这个方法是这个类中的精华,也是比较多人会提起的。

常用方法

public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

将字符从此序列复制到目标字符数组 dst。要复制的第一个字符在索引 srcBegin 处;要复制的最后一个字符在索引 srcEnd-1 处。要复制的字符总数为 srcEnd-srcBegin。要复制到 dst 子数组的字符从索引 dstBegin 处开始,

public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
    {
        if (srcBegin < 0)
            throw new StringIndexOutOfBoundsException(srcBegin);
        if ((srcEnd < 0) || (srcEnd > count))
            throw new StringIndexOutOfBoundsException(srcEnd);
        if (srcBegin > srcEnd)
            throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

public AbstractStringBuilder append(String str)

按顺序追加 String 变量中的字符,使此序列增加该变量的长度。如果 str 为 null,则追加 4 个字符 “null”。

public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        //如果需要扩容,会在这个方法中进行扩容
        ensureCapacityInternal(count + len);
        // 将str中的值在value后添加
        str.getChars(0, len, value, count);
        // 改变长度
        count += len;
        return this;
    }

这个方法中需要注意的是扩容机制,因为如果不需要扩容的话,这个方法是很简单且高效的。

public AbstractStringBuilder delete(int start, int end)

移除此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符,如果不存在这种字符,则一直到序列尾部。如果 start 等于 end,则不发生任何更改。

public AbstractStringBuilder delete(int start, int end) {
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (end > count)
            end = count;
        if (start > end)
            throw new StringIndexOutOfBoundsException();
        int len = end - start;
        if (len > 0) {
            System.arraycopy(value, start+len, value, start, count-end);
            count -= len;
        }
        return this;
    }
public AbstractStringBuilder deleteCharAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        System.arraycopy(value, index+1, value, index, count-index-1);
        count--;
        return this;
    }

对于需要移除的序列,并没有做一个清空的操作,只是将后面的值覆盖前面的值,并将长度缩减而已。

public AbstractStringBuilder replace(int start, int end, String str)

使用给定 String 中的字符替换此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符,如果不存在这种字符,则一直到序列尾部。先将子字符串中的字符移除,然后将指定的 String 插入 start。(如果需要,序列将延长以适应指定的字符串。)


public AbstractStringBuilder replace(int start, int end, String str) {
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (start > count)
            throw new StringIndexOutOfBoundsException("start > length()");
        if (start > end)
            throw new StringIndexOutOfBoundsException("start > end");

        if (end > count)
            end = count;
        int len = str.length();
        int newCount = count + len - (end - start);
        //如果有需要,需要扩容
        ensureCapacityInternal(newCount);
		
        System.arraycopy(value, end, value, start + len, count - end);
        str.getChars(value, start);
        count = newCount;
        return this;
    }

这个方法的大概操作是这样的:先将value的值分为三段,第一段是删除区前面的称为d1,第二段是删除区称为d2,第三段是删除区之后的称为d3,

  1. 将d3的数据复制到 Vaule[start + len] 之后。(len的空间是为为替代的字符串空出来的)
  2. 将str的字符复制到value[start]之后

public String substring(int start, int end)

public String substring(int start, int end) {
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (end > count)
            throw new StringIndexOutOfBoundsException(end);
        if (start > end)
            throw new StringIndexOutOfBoundsException(end - start);
        return new String(value, start, end - start);
    }

很简单,直接new出一个新对象返回

说明

这个类中的方法很多,我们有一个一个的复制出来,只是将我觉得有代表性的方法复制出来和大家分享。

AbstractStringBuilder类涉及的设计模式

暂无发现

AbstractStringBuilder类的阅读感想

这是一个抽象类,但是我看完源码之后发现,就只有toString()方法是抽象的,其他都不是。也都基本实现了所有的功能。我觉得这个类设计出来可能就是作为一个代表。就是提供一个模板给我们去实现自己的可变的字符串的类。
这个类的主要让我们学习的是他的扩容方法,这个方法我觉得思考的地方有两个:什么时候扩容?一次扩容要多少合适?从源码中“minimumCapacity - value.length > 0”我们可以看出,只有当需要的容量大于数组的容量的时候才会扩容。并且一次扩容的数量是上一次的两倍加2。
阅读这个源码,我发现这个类的源码很多,刚刚开始的时候有点恐惧,感觉好像要花很多的时间来阅读和理解,其实不然,当我们深入了解之后,越是往下读,越是感觉了然于胸。我读了一遍之后,往回去看,有一种油然而生的自豪感。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JDK源码阅读之AbstractStringBuilder类 的相关文章

  • Web安全漏洞之:JDK1.5环境下扫描远程调试端口导致JVM崩溃【JDWP exit error JVMTI_ERROR_NONE(0)】

    问题描述 对运行在JDK 1 5版本下的java应用服务器进行端口扫描 扫描的方式可以用相关扫描软件 最简单的是直接用ping telnet命令 有闲情还可以自己写一段代码进行socket连接 扫描时会发现java进程crash 经测试百发
  • Ubantu 安装 Oracle JDK

    1 Oracle 官网下载 jdk 压缩包 Java Downloads Oracle 2 下载的 jdk 18 linux aarch64 bin tar gz 通过 sftp 上传到 Ubantu 3 解压 jdk 18 linux a
  • 阿里云—(1)安装JDK 11

    1 查看原有JDK版本 若新装系统 可忽略 yum list installed grep java 如图所示 代表已安装 2 查看yum库内所有的JDK版本 yum y list java 当你已经安装了某个版本后 显示的为本地安装包 下
  • MyEclipse下配置WebLogic10(转)

    MyEclipse下配置WebLogic10 转 安装 WebLogic 比较容易 在这里就不再累述了 大家可以参阅相关文档 现在着重讲一下 WebLogic 的配置 因为后面在配置 MyEclipse 时将用到这里的配置信息 运行开始 g
  • jdk下载百度云(windows×64-7,8,10)

    之前找了很久 好多都要很多积分 所以我就给大家整理到百度云盘 https pan baidu com s 1UgiZf6R8PNtnlTDNW N2Kw 提取码 o6cp
  • 将 Tocmat5.0 注册为 Windows 的服务程序

    将 Tocmat5 0 注册为 Windows 的服务程序 步骤 1 下载 Tomcat 5 0 x 不要下载安装版本 2 解压到 TOMCAT HOME 3 安装或者从别处拷贝JRE 推荐拷贝 可以删除不需要的文件 如文档等 4 在 TO
  • CentOs7.5安装JDK1.8详细步骤

    1 先检查系统中有没有自带的JDK 有就卸载 查询命令 rpm qa grep jdk color 卸载命令 rpm e nodeps 软件名称 再次查询检查是否成功 rpm qa grep jdk color 没有提示也没有报错就是操作成
  • JDK 监控和故障处理工具

    JDK 监控和故障处理工具总结 JDK 命令行工具 这些命令在 JDK 安装目录下的 bin 目录下 jps JVM Process Status 类似 UNIX 的 ps 命令 用户查看所有 Java 进程的启动类 传入参数和 Java
  • WIN7环境下cmd javac不是内部或外部命令

    一般步骤如下 网上摘抄部分 JAVA HOME指明JAVA安装路径 值设为 C Program Files Java jre7 刚才安装时所选择的路径 每个人可能不一样 此路径下包括lib bin jre等文件夹 Path值设为 JAVA
  • 异常:java lang AbstractMethodError

    通常在尝试调用抽象方法时抛出此 java lang AbstractMethodError 通常 此错误是在编译时本身识别的 如果在运行时抛出此错误 则该类必须不兼容 与先前存在的类不兼容 更改 因此 它是IncompatibleClass
  • 有哪些老程序员都知道对新程序员很有用的经验

    回想起自己刚步入职场的时候 接到任务的心态就是尽快搞完 只要没做完就怕耽误了整个团队 还怕领导觉得自己能不行 怕被开除等等 但是每次完成之后 都有错误 编译通过了 逻辑又有问题 自己就是不断的修改当中 时间久了自己写的代码自己都不愿意看 因
  • 解决“The method XXXXXX of type XXXXXXXXX must override a superclass method”

    我的Eclipse版本是3 6 1 Override 时出现以下错误 The method XXXXXX of type XXXXXXXXX must override a superclass method 上网搜索原来原因是 实现类里面
  • 一文搞定java8中的重要特性

    文章目录 Lambda表达式 函数式接口 四大内置函数接口 接口的默认方法和静态方法 方法引用 重复注解 更好的类型推断 拓宽注解的应用场景 Optional Stream Date Time API Base64 并行数组 并发性 JVM
  • jdk8源码之Queue-ArrayQueue

    关于队列这个数据结构 大家应该都是比较熟悉 列队是一种先进先出 FIFO 的数据结构 删除操作只能在表的头部 插入操作只能在表的尾部 Queue一般是作为一个缓冲队列使用的 简单举例 生产端的生产速度偶尔会大于消费端的消费速度 但又不想等待
  • JDK源码阅读之AbstractStringBuilder类

    AbstractStringBuilder类源码阅读 AbstractStringBuilder类的作用 AbstractStringBuilder类的类图 AbstractStringBuilder类的重点方法 属性变量 构造方法 精华方
  • 橘子学java之java中的协程

    一 关于协程 最近jdk19上了 java开始支持虚拟线程了 也就是所谓的协程 java的协程库是官方是这个https openjdk org projects loom 我指的是oracle的java 阿里那个well的早就支持了 只是官
  • (转) serialVersionUID作用

    Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的 在进行反序列化时 JVM会把传来的字节流中的serialVersionUID与本地相应实体 类 的serialVersionUID进行比较 如果相
  • 升级Linux中的默认JDK的版本

    我用的Linux是 红帽企业级Linux AS版 TLF SOFT Redhat Enterprise Linux AS V4 0 UPDATE 7 DVD 因工作需要 将Linux中默认安装的Jdk 版本为1 4 进行升级 将升级的经验和
  • 电脑上安装多个JDK版本时如何自由切换

    文章目录 前言 一 安装JDK 二 设置系统变量 2 1 设置JAVA HOME 2 1 1 添加JAVA HOME VERSION 2 2 设置Path 2 2 1 添加Path 三 验证结果 前言 使用java的过程中 难免会遇上JDK
  • 服务器乱码专栏问题一:String.getBytes()获取值乱码

    本文建议阅读时长 15mins 前记 最近笔者工作比较繁忙 导致本来应该有很多博客需要填坑 一直也没有静下心来好好整理下 今天蹭着夜深人静加之阵阵柔和的轻音乐正好先写上一篇 也算是为自己乱码专栏开个头 当然本专栏主要解决Tomcat服务器以

随机推荐

  • sqlserver转换时间为字符串

    convert varchar 8 getdate 112 把
  • 文件预览:使用xlsx预览excel文件

    文件预览系列 mavon editor预览Markdown文件 xlsx预览excel文件 注意事项 多sheet页的情况需要自己手动处理 一 安装插件 xlsx 我目前使用的是0 17 5版本 之前有一次升级后报错 如果xlsx内部报错
  • C++deque容器deque 排序

    C deque容器deque 排序 功能描述 利用算法实现对deque容器进行排序 include
  • 关于BMC ipmi oem cmd和redfish

    ipmi是一个适用于bmc的标准协议 开发者可以通过ipmi oem cmd和bmc交互 oem cmd的实现与组成 均为unsigned char类型 NetFunction Cmd Request data Response data
  • Avue 远程搜索输入框,联动赋值其他组件 v2.7.10及以下

    Avue版本 v2 7 10及以下适用本文 v2 8 0及以上版本点这里 文章目录 Avue 远程搜索输入框 联动赋值 前言 一 基于avue自带属性实现 效果差 二 基于element ui实现 效果好 总结 Avue 远程搜索输入框 联
  • 用户登录非常慢报如下错误/usr/bin/xauth: timeout in locking authority file /home/user/.Xauthority

    一般是因为在创建用户时 用户家目录属组和属主不对导致 以最简单的解决办法就是给用户家目录赋予用户的所有权限就能解决 再次登录时 会重新创建一个这样的文件 下次登录就快了 chow user user user
  • 【JavaScript】Function的祖传方法call与apply

    引言 内容速递 看了本文您能了解到的知识 在本篇文章中 将带你了解什么是call和apply call和apply的用途 如何手写call和apply以及call和apply的使用场景 1 什么是call和apply call 和apply
  • ORB SLAM在Ubuntu14.04下环境配置

    在ubuntu14 04下安装Opencv2 4 9 安装 OpenCV 步骤一 创建目录 mkdir opencv cd opencv 步骤二 卸载任何以前安装的ffmpeg和x264软件 sudo apt get qq remove f
  • 面试经典(16)--二叉树根节点到指定节点的路径

    题目描述 给定一棵二叉树和二叉树中一个节点 输出根节点到指定节点间的路径 10 5 12 4 7 指定节点7 那么输出路径应该是10 5 7 分析与解法 这个题目是在我做过蛮多二叉树的题目之后总结的一道题目 发现很多题目都可以抽象出来这个题
  • VS code 显示中文异常解决办法

    从https www zhihu com question 34415763得到问题解决办法 现做如下总结 异常原因 VSCODE默认是UTF 8编码打开文件的 如果遇到了像GB18030 GBK等等的编码 就显示乱码了 解决办法如下 1
  • IDEA中Translation插件无法使用怎么办?

    昨天一个小偷 来我家偷钱 我们一起找了一晚上 问题 谷歌翻译退出中国了 导致我的 IDEA 翻译插件 Translation 也不能用了 会出现这样的错误 更新 TKK 失败 请检查网络连接 解决办法 使用百度翻译 很多翻译都收费 百度翻译
  • 用jquery实现选项卡效果(非常漂亮,带动画效果)

  • Map和String的相互转化

    Java中的Map集合与String的相互转化 代码如下 package com jianhu Test import java util Arrays import java util HashMap import java util M
  • electron-store 本地储存数据

    elelctron store elelctron store 是很好的本地储存库 https www npmjs com package electron store 使用 npm i elelctron store 设置 electro
  • BurpSuite武器库打造之环境搭建和API介绍(下)

    0x00 前言 接上篇丹丹妹 我又给大家带来了下篇 还是以python为开发语言 如有错误的地方还望大家多指正 轻喷 然后呢这边亲亲建议大家代码这种东西还是要多敲 多踩坑 毕竟伟大的爱情家周树人老先生说过只有痛过才能在心底留下不可磨灭的记号
  • 长草(Python)

    题目描述 小明有一块空地 他将这块空地划分为 n 行 m 列的小块 每行和每列的长度都为 1 小明选了其中的一些小块空地 种上了草 其他小块仍然保持是空地 这些草长得很快 每个月 草都会向外长出一些 如果一个小块种了草 则它将向自己的上 下
  • 【转】山寨一个 Boost.Bind

    原文地址 http www cppblog com Streamlet archive 2012 04 21 172241 html 点击打开链接 一直比较好奇 boost bind 里面占位符和参数的顺序是怎么实现的 也一直看不太懂这方面
  • 2023年最火副业:Python爬虫兼职,一周赚7800元,一天只要两小时 !

    下写了5 6年Python 期间写了各种奇葩爬虫 挣各种奇葩的钱 写这篇文章总结下几种爬虫挣钱的方式 1 最典型的就是找爬虫外包活儿 这是网络爬虫最通常的的挣钱方式 通过外包网站 熟人关系接一个个中小规模的爬虫项目 一般向甲方提供数据抓取
  • 开发者须知,App和小程序须备案,否则面临清退!

    备案并不陌生 前端开发的老铁肯定熟悉 若你的网站未备案情况下 在国内的服务器是无法访问的 所谓备案 通常指的就是ICP备案 需要把你经营的信息 给相关部门进行报备 简而言之 就是网络上的 营业执照 这么做的目的 就是维护网络的安全 防止在网
  • JDK源码阅读之AbstractStringBuilder类

    AbstractStringBuilder类源码阅读 AbstractStringBuilder类的作用 AbstractStringBuilder类的类图 AbstractStringBuilder类的重点方法 属性变量 构造方法 精华方