String与StringBuilder与string.format

小柊 发表于 2015年12月03日 17时52分47秒

String类型对于各个开发人员来说相信是再熟悉不过的类型了,它可以用于储存和操作字符串类型。但对于一些初学者来说StringBuilder就不怎么熟悉了。

从字面意义上来看,StringBuilder可以理解为字符串构造器,那为什么微软和Oracle分别在各自的.net Framework和Java中都添加了这么一个类呢?

 

一、字符串的不可变性

在此之前我们要知道一件事情,就是String的不可变性:一旦被创建,就不能修改它的值。

我估计这时候台下肯定有人会站起来说不服,然后给我看这么几行代码:

 

在上面,字符串变量str在第二行进行了加运算,即“Hello ”字符串与“World! ”相加。我们可以看到倒数第二行的输出代码中str确确实实的变成了“Hello World!”

可是最后的str变量还是原来的str变量吗?我们重新运行刚刚的程序,这次使用单步执行,用Visual Studio的“立即”追踪str在内存中的地址变化:

 

很明显,str变量在内存中的地址随着第二步的字符串相加计算随之改变了!如果只是像int类型那样的运算是不可能在内存中移动的,这从结果上证明了String类型的不可变性。

那么从原理上呢?

我们把光标放在String类型上,按F12进入String类型内部。一进去我们就看到非常明显的一行代码:

 

注意到那个被红框标记的sealed了吗?这个sealed和Java中的final标记类似,sealed修饰符表示此类为密封类,当在程序中密封了某个类时,其他类不能从该密封类继承。使用密封类可以防止对类型进行自定义。

接下来我们可以再看一下String类型提供的一些会修改字符串的方法,比如说Remove和Replace方法。

 

都不出意料的是重新返回一个新的String类型,并不会在字符串本身进行修改。

可见字符串类型的不可变性体现在其一旦被创建,就无法去修改它的值;所有对已创建的字符串对象的修改都是通过重新创建一个新的字符串对象,然后再修改变量名的内存地址引用完成。

或许你觉得这无关紧要,反正.net Framework和JVM有GC,但是你要知道,在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。创建完成后.net Framework或者JVM还要对对象进行跟踪,以便进行垃圾回收。在一些特定的环境例如服务器中,这样的操作是非常昂贵的。

所以因为String的不可变性,像以下字符串拼接代码在实际运行中不仅效率低,还会在内存中创建出不必要的字符串垃圾副本

 

二、可变的StringBuilder

为了解决String的不可变性带来的性能问题,微软和Oracle分别在自家的.net Framework和Java中添加了StringBuilder类,StringBuilder是变长的,您可以自由的在字符串末尾添加或删除字符,如果操作后有超过StringBuilder内部的缓冲区容量,StringBuilder才会去申请增大缓冲区大小。

这样做的效果显而易见。下面我就来实际展示一下String和StringBuilder两者间的性能差距。

本来是想循环一亿次的,只是String的循环添加字符测试真的是非常的慢,后来只能将次数下到一百万次(当然这样也非常的耗时)。

 

测试结果如下图:

 

可以看见如果只是使用String类型进行字符串拼接,不仅耗时长,还会频繁触发垃圾回收器(因为内存中有大量的垃圾副本)。打开任务管理器查看一下内存波动,可以看到在进行String循环添加字符测试时内存波动非常明显,说明测试中有大量的对象创建和销毁,而StringBuilder在循环添加字符的时候则是普通的线性增长。

 

三、string.Format()函数

从上面的测试中我们可以发现连接多个字符串时StringBuilder明显优于String。

还记得我们在第一章里提到的那个例子吗?

 

有些时候像这样只是少量的字符串连接,如果这时候也要去使用StringBuilder也未免太麻烦了。码代码最重要的就是代码的简洁。所以在这里我要提一下string.format()函数。

在使用了string.format()函数之后,上面的代码就只需要这样:

 

它同样不会在内存中产生垃圾副本。

 

四、写在最后

然后在Java里,除了StringBuilder以外,还有一个StringBuffer。两者的区别如下:

1.StringBuilder是非线程安全的,而StringBuffer是线程安全的;

2.在单线程环境里StringBuilder比StringBuffer快;

3.微软.net Framework笑了:

 

小柊

2015年12月3日 17:51:13

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注