StringBuffer/StringBuilder与使用加号“+”直接拼接字符串的区别

一、使用“+”拼接字符串

1.字符串常量内存分析。

  首先我们要了解到,字符串常量是存储在常量池中的。在JDK1.7以前,常量池处于方法区当中。此时hotspot虚拟机对方法区的实现为永久代。对于永久代,大家需要了解他的一个特性,那就是GC不会对永久代内的数据进行垃圾回收

2.String类型特性。

  String类型很重要的一个特性就是,字符串是不可变的,他们的值在创建后无法更改。看下面两行代码:

        String s = "aaa";
        s = "abc";

  当执行第一行代码时,栈内存入栈了一个引用s,常量池存储了一个字符串常量“aaa”,s指向了“aaa”的地址。当执行第二行代码时,并不是"aaa"的内容改变成了“abc”,而是常量池中又存储了字符串常量“abc”,s指向的地址改为了“abc”的地址。“aaa”无引用指向,成为系统垃圾。

3.使用“+”拼接字符串时内存分析。

  根据上述永久代和String类型的特性,当我们使用“+”拼接字符串时就会发生浪费空间的问题。详情请看下面一段代码:

	String text1 = "abc";
	String text2 = "def";
	String text3 = "gh";
	text1 = text1+text2+text3;
	System.out.println(text1);

  此段代码看上去没有任何问题,运行后也输出了“abcdefgh”。那究竟为何会浪费空间呢?但让我们来分析一下此时内存中的变化。
  首先,前三条代码执行后,栈内存中已经入栈了text1,text2,text3三个变量,常量池中也存储了三个字符串常量,栈中的三个变量分别指向了所对应的地址。如下图:
创建String变量时的内存分析
  当执行第四行代码,字符串进行了拼接。此时注意,text1+text2+text3看起来是一个式子,但在执行过程中,内存中会新增加两个字符串常量。第一个是text1和text2拼接所生成的字符串(“abcdef”),第二个是第一个生成的字符串和text3字符串拼接后所生成的字符串(“abcdefgn”)。拼接完成后text1所指向的地址将会修改成最后生成的字符串地址,此时常量池中则出现了两个没有任何引用指向的常量,系统垃圾“abc”和“abcdef”。如下图:
字符串拼接后的内存
  而根据永久代的特性,这两个垃圾将不会被GC回收,成为“永久垃圾”!
此处看上去好像只是内存中多出了两个字符串而已,但如果业务规模大了起来,如果这种拼接是发生在一个大规模的循环体中,那么产生的垃圾可就不只是两个而已了,将会造成系统空间的大量浪费。

二、StringBuffer/StringBuilder拼接字符串分析

1.StringBuffer/StringBuilder对象创建时内存分析

  通常我们创建StringBuffer/StringBuilder对象方式如下:(以StringBuffer为例)

	StringBuffer s1 = new StringBuffer("abcd");

  当new关键字一出现,我们就应当知道,此时要创建一个对象了。而在Java中new出来的对象的实例存放在堆内存中,对象的引用存放在栈内存中。如下图:
创建StringBuffer对象的内存图

2.StringBuffer/StringBuilder拼接字符串分析

  与String类型不同的是,StringBuffer/StringBuilder是可变字符串,他们的值可以发生变化。请看以下代码:

        StringBuffer s1 = new StringBuffer("abcd");
        s1.append("efg");

  第一行代码执行后内存已经分析过,如上图。当执行第二行代码时,append()方法的作用就是在末尾拼接字符串,由于StringBuffer是可变字符串,所以拼接即发生在当前StringBuffer的实例上,无需再新建实例。即改变了原实例内的字符串内容,s1依然指向原地址。内存变化如下:
使用StringBuffer拼接字符串后内存变化
  以上例子均使用StringBuffer实现,StringBuilder进行拼接字符串操作时与StingBuffer相同。由此可见,使用StringBuffer/StringBuilder拼接字符串不会造成空间的浪费。

三、总结

  综上所述,当我们有需求要拼接字符串时,应尽量的去使用StringBuffer或StringBuilder。尽管“+”的使用非常便捷,但当业务需求变大时,造成的浪费可能会远远超出我们的想象。
  以上内容全是本人自己的理解,如哪里有错误,请大家及时指出,我会在确认后尽快修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值