相关学习推荐:java基础教程
上篇文章我们深入分析了string的内存和它的一些特性。本篇文章我们深入的来分析一下与string相关的另外两个类,它们分别是stringbuilder和stringbuffer。这两个类与string有什么关系呢?首先我们看下下边这张类图:
从图中可以看出stringbuilder和stringbuffer都继承了abstractstringbuilder,而abstractstringbuilder与string实现了共同的接口charsequence。
我们知道,字符串是由一系列字符组成的,string的内部就是基于char数组(jdk9之后基于byte数组)实现的,而数组通常是一块连续的内存区域,在数组初始化的时候就需要指定数组的大小。上一篇文章中我们已经知道string是不可变的,因为它内部的数组被声明为了final,同时,string的字符拼接、插入、删除等操作均是通过实例化新的对象实现的。而今天要认识的stringbuilder和stringbuffer与string相比就具有了动态性。接下来就让我们一起来认识下这两个类。
一、stringbuilder
在stringbuilder的父类abstractstringbuilder 中可以看到如下代码:
abstract class abstractstringbuilder implements appendable, charsequence { / * the value is used for character storage. */ char[] value; / * the count is the number of characters used. */ int count;}复制代码stringbuilder与string一样都是基于char数组实现的,不同的是stringbuilder没有final修饰,这就意味着stringbuilder是可以被动态改变的。接下来看下stringbuilder无参构造方法,代码如下:
/ * constructs a string builder with no characters in it and an * initial capacity of 16 characters. */ public stringbuilder() { super(16); }复制代码在这个方法中调用了父类的构造方法,到abstractstringbuilder 中看到其构造方法如下:
/ * creates an abstractstringbuilder of the specified capacity. */ abstractstringbuilder(int capacity) { value = new char[capacity]; }复制代码abstractstringbuilder的构造方法内部初始化了一个容量为capacity的数组。也就是说stringbuilder默认初始化了一个容量为16的char[]数组。stringbuilder中除了无参构造外还提供了多个构造方法,源码如下:
/ * constructs a string builder with no characters in it and an * initial capacity specified by the {@code capacity} argument. * * @param capacity the initial capacity. * @throws negativearraysizeexception if the {@code capacity} * argument is less than {@code 0}. */ public stringbuilder(int capacity) { super(capacity); } / * constructs a string builder initialized to the contents of the * specified string. the initial capacity of the string builder is * {@code 16} plus the length of the string argument. * * @param str the initial contents of the buffer. */ public stringbuilder(string str) { super(str.length() 16); append(str); } / * constructs a string builder that contains the same characters * as the specified {@code charsequence}. the initial capacity of * the string builder is {@code 16} plus the length of the * {@code charsequence} argument. * * @param seq the sequence to copy. */ public stringbuilder(charsequence seq) { this(seq.length() 16); append(seq); }复制代码这段代码的第一个方法初始化一个指定容量大小的stringbuilder。另外两个构造方法分别可以传入string和charsequence来初始化stringbuilder,这两个构造方法的容量均会在传入字符串长度的基础上在加上16。
1.stringbuilder的append操作与扩容
上篇文章已经知道通过stringbuilder的append方法可以进行高效的字符串拼接,append方法是如何实现的呢?这里以append(string)为例,可以看到stringbuilder的append调用了父类的append方法,其实不止append,stringbuilder类中操作字符串的方法几乎都是通过父类来实现的。append方法源码如下:
// stringbuilder @override public stringbuilder append(string str) { super.append(str); return this; } // abstractstringbuilder public abstractstringbuilder append(string str) { if (str == null) return appendnull(); int len = str.length(); ensurecapacityinternal(count len); str.getchars(0, len, value, count); count = len; return this; }复制代码在append方法的第一行首先进行了null检查,等于null的时候调用了appendnull方法。其源码如下:
private abstractstringbuilder appendnull() { int c = count; ensurecapacityinternal(c 4); final char[] value = this.value; value[c ] = 'n'; value[c ] = 'u'; value[c ] = 'l'; value[c ] = 'l'; count = c; return this; }复制代码appendnull方法中首先调用了ensurecapacityinternal来确保字符串数组容量充值,关于ensurecapacityinternal这个方法下边再详细分析。接下来可以看到把"null"的字符添加到了char[]数组value中。
上文我们提到,stringbuilder内部数组的默认容量是16,因此,在进行字符串拼接的时候需要先确保char[]数组有足够的容量。因此,在appendnull方法以及ap
电脑怎么关闭开机密码 电脑开机取消登录密码的两种方法你们的邮箱证书到期了管理不了邮箱了独立云服务器版建网站怎么样php如何删除服务器文件网易企业邮箱微信小程序全面上线,邮件动态“易”手掌握!免费试用云服务器报价网站百度快照优化的方法有哪些小程序云开发好还是买服务器好