-
在java开发中,String类是我们经常用到的一个类,所以为了提高开发效率,jdk提供了一个字符串常量池,方便我们的使用。那么什么是字符串常量池呢,就是一个存储字符串的空间,例如
String s = “abc”; **“abc”**这个字符串就是存储在字符串常量池中,也就是建了一个 “abc” 字符串对象,而变量s中只是一个内存地址,指向字符串常量池中的 “abc” 字符串。如果要再次用到 “abc”
字符串,就直接在字符串常量池中获取,而无需在新建一个 “abc” 字符串对象。 -
那么同样是创建了一个字符串对象,String s = “abc”; 与 String s = new String(“abc”);
有什么区别呢?答案是:前者只创建了一个对象,在字符串常量池中,变量s在栈内存中,是一个指向字符串常量池中的 "abc"
字符串位置的内存地址;而后者创建了两个对象,一个在字符串常量池中,一个在堆内存中,堆内存中的对象存储的是指向字符串常量池中的
"abc" 字符串位置的内存地址,引用s在栈内存中,也是一个内存地址,不过是指向的堆内存中的对象。 -
String类我们也经常用来进行字符串拼接,例如:
-
但是这种通过 “+”
进行字符串拼接的方式会创建过多的字符串对象,而给字符串常量池造成压力,为了避免这种情况,我们通常使用StringBuffer或者StringBuilder的append()方法来进行字符串的拼接。
通过源码可以看到,字符串是以char[]数组的形式存储的
注意这里的char[]数组是以final关键字修饰的,即只要创建了这个数组,它就不可变了,这也是为什么用String进行字符串拼接会创建多个字符串对象的原因。
我们再来看看StringBuffer类中的源码
可以看出在创建StringBuffer对象的时候,内部会调用父类中的方法,初始化char[]数组的容量为16
然后再来看看拼接字符串的append()方法
会调用父类中的append()方法,点进去可以看到
再点进getChars(),可以看到如果数组容量不足,内部会进行自动扩容(System.arraycopy())
-
但是为了优化StringBuffer()的性能,在创建StringBuffer对象的时候尽可能给定一个合适的初始化容量,减少底层数组的扩容次数
- StringBuilder和StringBuffer一样可以进行字符串拼接,不过一个是线程不安全的的,效率高;一个是线程安全的,效率低(有synchronized修饰符)
- 具体原因也可以看源码…
java中String、StringBuffer、StringBuilder的区别
最新推荐文章于 2024-07-24 17:47:13 发布