String,StringBuffer,StringBuilder区别

  1. StringBuffer和StringBuilder的append比string的"+""快
String str = "a";  
str+="b";

我们可以看到,初始String值为"a",然后在这个字符串后面加上新的字符串"b",这个过程是需要重新在栈堆内存中开辟内存空间的,最终得到了“ab”字符串也相应的需要开辟内存空间,这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费。为了应对经常性的字符串相关的操作,引入了两个新的类——StringBuffer类和StringBuild类来对此种变化字符串进行处理。
内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的

image

从javap的解析结果可以看出,在常量池中生成了 a 和 b两个字符串对象,并没有ab这个字符串对象。在堆中用两个new创建了两个String对象,然后通过StringBuilder对象调用append方法进行两次字符串的添加操作,最后用StringBuilder的toString方法进行返回了一个堆中的字符串对象
(jdk9以后版本的虚拟机,则是调用虚拟机自带的InvokeDynamic拼接字符串,并且保存在堆中)。

所以,Strin str = new String(“a”) + new String(“b”) 在堆中创建了三个字符串对象(a字符串对象,b字符串对象,ab字符串对象),在堆中的常量池中创建了2个字符串对象(a字符串对象,b字符串对象),一共创建了5个对象。

StringBuilder是对对象自身进行操作,堆中只会创建一个对象。
image

  1. 但如果变成以下,string就比StringBuild和StringBuffer快
String str = "a"+"b";

String str =“a” + “b” 创建了1个字符串对象,在java堆中的常量池中

这是因为String和我们其它类型的变量不同,其它的非基本类型对象的值、数据都存储在java的堆中,而String类型的变量的值是存储jvm在方法区中的字符串常量池中的。(和jvm有关)当我们执行:String str = “a”+“b”;这句话的时候,String会自动把这个对象的值看成"ab",然后在方法区中如果找到了值同样为"ab"的,就会直接让str句柄指向它,也就是说,我们的这句代码现在相当于:

String str = "ab";

String常量的累加操作中,编译器会进行优化,如果是 String str = “a” + “b”,那相当于String str = “ab”; ,常量池中会创建一个ab的对象。 ldc #2 // String ab 然后 将int,float或String型常量值从常量池中推送至栈顶即可。等于只在常量池中创建了一个对象,jdk1.8的常量池在java堆中,等于在java堆的常量池创建了一个对象。

这可比之前的String用法一遍遍反复地去创建对象回收对象快多了,因此,即使重复10万次依然还是很快。

String str = new String(“a”) + new String(“b”) 创建了5个字符串对象,3个在java堆中,2个在java堆的常量池中。

String s1 = new String(“str”);建立两个对象
在堆中创建保留对象,在栈中保留地址,在常量池中存放一份复制的对象

  1. StringBuffer线程安全 源代码上有synchronized
    StringBuilder没有

  2. 总结:

如果要操作少量的数据用 String;
多线程操作字符串缓冲区下操作大量数据 StringBuffer;
单线程操作字符串缓冲区下操作大量数据 StringBuilder。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值