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类 的相关文章

  • jdk安装与环境变量配置,看这篇就够了

    文章目录 场景 jdk 下载安装 如何环境变量的配置 总结 场景 在做 java 开发或者 android 开发 经常会碰到 jdk 安装与环境变量的配置 每次配置的时候 经常需要去查看一下 而且偶尔还会出现错误 这里就把这块详细的记录一下
  • Web安全漏洞之:JDK1.5环境下扫描远程调试端口导致JVM崩溃【JDWP exit error JVMTI_ERROR_NONE(0)】

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

    一 安装jdk 不同平台安装不同的包 Oracle官方下载 Oracle官方各版本 推荐安装jdk1 8 32位操作系统 准备jdk xxx windows i586 exe 64为操作系统 准备jdk xxx windows x64 ex
  • Ubantu 安装 Oracle JDK

    1 Oracle 官网下载 jdk 压缩包 Java Downloads Oracle 2 下载的 jdk 18 linux aarch64 bin tar gz 通过 sftp 上传到 Ubantu 3 解压 jdk 18 linux a
  • JDK源码汇总

    JDK源码汇总 持续更新中 Appendable
  • Java环境变量的配置

    最近有朋友问到环境变量的配置 下面以Windows10系统为例进行Java环境变量配置说明 1 右键点击 此电脑 选择 属性 项 2 点击 高级系统设置 在弹出的系统属性框中 选择 高级 选项卡 默认即显示该选项卡 点击 环境变量 3 在弹
  • Window11下载安装jdk8-jdk11与环境变量的配置

    目录 1 下载jdk 1 1 jdk8下载链接 请点击网址 1 2 jdk11下载链接 请点击网址 2 安装jdk 3 配置环境变量 3 1 打开设置 3 2 点击系统信息 3 3 高级系统设置 3 4 点击环境变量 3 5 新建系统变量
  • linux下jdk的安装

    目录 获取文件下载地址 官网获取文件下载地址 下载文件到指定目录下并修改改文件名 卸载已经存在的JDK 查看系统是否安装JDK 卸载JDK 安装JDK 赋予权限 安装JDK 配置JDK的环境变量 在配置文件的最底部加上以下配置 重新刷新配置
  • eclipse中提示的时候总是出现未响应的解决方案

    将eclipse自带的jre换成自己安装的jdk的jre Eclipse Window Preferences Java Installed JREs 选择jdk的安装路径 然后确定 之后勾选jdk就行了
  • Java Calendar getActualMinimum()方法与示例

    Calendar类的getActualMinimum 方法 Calendar Class getActualMinimum method getActualMinimum method is available in java util p
  • 使用yum命令安装jdk1.8没有jps命令

    问题 使用yum命令安装jdk1 8后 不能使用jps 这是由于没有openjdk devel这个包 使用yum命令下载 yum install java 1 8 0 openjdk devel x86 64 下载完成之后就可以使用jps命
  • 基于JDK1.8 的LinkedList源码分析

    基于JDK1 8 的LinkedList源码分析 代码注释 JDK版本 jdk1 8 0 181 package java util import java util function Consumer Doubly linked list
  • 异常:java lang AbstractMethodError

    通常在尝试调用抽象方法时抛出此 java lang AbstractMethodError 通常 此错误是在编译时本身识别的 如果在运行时抛出此错误 则该类必须不兼容 与先前存在的类不兼容 更改 因此 它是IncompatibleClass
  • JDK1.8 下载与安装

    JDK安装 JDK1 8下载 下载链接 https www oracle com java technologies javase javase jdk8 downloads html 根据操作系统版本下载 这里以win10 64位操作系统
  • JDK1.8 AbstractQueuedSynchronizer的实现分析(上)

    深度解析Java 8 JDK1 8 AbstractQueuedSynchronizer的实现分析 上 作者 刘锟洋 发布于 2014年7月31日 http www infoq com cn articles jdk1 8 abstract
  • 浅谈Class.forName()在JDBC中的作用

    目录 1 Class forName 有什么作用呢 2 为什么不直接new 3 为什么删除Class forName com mysql jdbc Driver 还是可以运行 JDBC是Bridge模式的典型应用 DriverManager
  • Ubuntu下安装JDK图文教程详解

    操作系统 Ubuntu 11 10 我们选择的是jdk1 6 0 30版本 安装文件名为jdk 6u30 linux i586 bin 1 复制jdk到安装目录 1 假设jdk安装文件在桌面 我们指定的安装目录是 usr local jav
  • 橘子学java之java中的协程

    一 关于协程 最近jdk19上了 java开始支持虚拟线程了 也就是所谓的协程 java的协程库是官方是这个https openjdk org projects loom 我指的是oracle的java 阿里那个well的早就支持了 只是官
  • Java 内存模型及GC原理

    一个优秀Java程序员 必须了解Java内存模型 GC工作原理 以及如何优化GC的性能 与GC进行有限的交互 有一些应用程序对性能要求较高 例如嵌入式系统 实时系统等 只有全面提升内存的管理效率 才能提高整个应用程序的性能 本文将从JVM内
  • Java Web快速开发(1)Java 项目构建

    文章目录 Java 项目构建 1 Java 版本发展 2 集成开发环境 3 Java发布形式 1 扩展参数说明 2 JVM 内存回收机制 3 Java 程序分析调测工具 4 Maven Java 项目构建 1 Java 版本发展 EJB E

随机推荐

  • 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类的重点方法 属性变量 构造方法 精华方