一.代码演示
如上图所示,在连续对字符串进行增加时,两者的效率差距会非常大,那究竟时什么原因呢?
二.StringBuilder和String原理
StringBuilder和String底层其实都用的是char[]对字符串进行保存.
在StringBuilder中:
String中:
可以很明显的注意到,一个使用了final关键字一个则没有使用.那这个和效率有什么关系呢?请继续往下看:
当使用StringBuilder增加字符串时,调用append方法.
进行扩容的时候主要调用getChars方法.
在getChar方法里面调用了复制数组的方法,对字符串进行添加(ArrayList底层其实也调用的是该方法)
在对字符串增加完毕,请注意这里返回的是this,也就是当前StringBuiler对象,因为这里的char[]并没有加final关键字.
而在String中呢,因为它是不可变的,所以每次需要构建一个新的字符串对象,需要做申请内存,开辟空间等操作,所以没有StringBuilder效率高.
三.那为什么String中的char[]要用final修饰?
1.减少存储空间.
在编程时需要存储的信息绝大多数都是String类型,使用频率特别高.
String str1="a";
String str2="a";
如上,在我们需要对相同的字符串常量进行存储使用时,我们是希望它们指向同一个引用的,因为本身就是同样的内容,如果都单独开辟空间,岂不是有些太浪费内存了?
那如果指向同一个内存空间,又会带来问题,当我们将str1进行修改,str1=“b”;那么此时str2也将被修改,因为指向的是同一个内存地址,但这是我们不希望看到的,String在Java中是一个基础类型,我们需要对每个字符串进行单独处理,更不希望被其他字符串影响,那有什么办法实现呢?
最佳答案就是将String设计为final类型,当改变时不会被相互影响,同时设计了字符串常量池,使得相同的字符串不需要重复占用空间,可以说是很绝妙的设计了.
2.安全.
如果字符串是可变的,那么会引起很严重的安全问题。譬如,数据库的用户名、密码都是以字符串的形式传入来获得数据库的连接,或者在socket编程中,主机名和端口都是以字符串的形式传入。因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞。