Java中String类,StringBuffer类和StringBuilder类

底层分析:

(1)String类

String类对象代表不可变的字符序列。其底层结构如下:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
    private final char value[];

    
    private int hash; // Default to 0

    
    private static final long serialVersionUID = -6849794470754667710L;

其核心本质是被final修饰的数组value[],即String类型的字符串内容全部存储到value[]数组中,并且该数组被final修饰,也就是只能被赋值一次,之后不能被改变。因此每次对String类进行改变的时候都会生成一个新的String对象,然后将指针指向新的String对象,所以经常要改变字符串的话,不要使用String类,因为每次生成对象都会对系统性能产生影响,特别是当内存中引用的对象多了以后,JVM的GC就会开始工作,性能就会降低。

(2)StringBuffer类

StringBuffer类对象代表线程安全的可变字符序列。StringBuffer类增加了线程安全的同步机制,而为了保证线程安全是需要付出性能降低的代价。其底层结构如下:

public final class StringBuffer extends AbstractStringBuilder
                                implements java.io.Serializable, CharSequence



abstract class AbstractStringBuilder implements Appendable, CharSequence {
    
    char[] value;

StringBuffer类继承了抽象类AbstractStringBuilder,而在抽象类中也使用了数组value[],并且该数组没有final修饰,即StringBuffer类型的字符串内容全部存储到value[]数组中,并且该数组未被final修饰,也就是可以被更改的。通过append(),delete(),insert()等方法可以更改字符串内容。

使用StringBuffer类时,每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用,所以在字符串对象经常改变的情况下,推荐使用StringBuffer类。

(3)StringBuilder类

StringBuilder类对象代表非线程安全的可变字符序列。StringBuilder类是JDK1.5发布的,它和StringBuffer类本质上没有什么区别,就是去掉了保证线程安全的部分,较少了开销,提高了效率。其底层结构如下:

public final class StringBuilder extends AbstractStringBuilder
                                 implements java.io.Serializable, CharSequence


abstract class AbstractStringBuilder implements Appendable, CharSequence {

    char[] value;

StringBuilder类继承了抽象类AbstractStringBuilder,而在抽象类中也使用了数组value[],并且该数组没有被final修饰,即StringBuilder类型的字符串内容全部存储到value[]数组中,并且该数组未被final修饰,也就是可以被更改的。通过append(),delete(),insert()等方法可以更改字符串内容。

比较:

(1)长度是否可变

String类本质是被final修饰的char数组,因此长度是不可改变的,在对String字符串进行修改时,都是重新创建对象。

StringBuffer类和StringBuilder类本质是未被final修饰的char数组,因此可以被多次修改,并且不产生新的对象。

(2)执行效率

StringBuilder>StringBuffer>String

(3)应用场景

字符串不经常发生变化的业务场景下(如常量的声明等),用String类。

单线程情况下,如有大量的字符串操作(如JSON的封装),用StringBuilder类。

多线程情况下,如有大量的字符串操作(如HTTP参数解析和封装),用StringBuffer类。

测试代码如下:

public static void main(String [] args){
		String str="";
		long a=System.currentTimeMillis();
		long a1=Runtime.getRuntime().freeMemory();
		for(int i=0;i<10000;i++){
			str=str+i;
		}
		long b=System.currentTimeMillis();
		long b1=Runtime.getRuntime().freeMemory();
		System.out.println("String字符串拼接用时:"+(b-a));
		System.out.println("String字符串拼接使用的内存:"+(a1-b1));
		
		
		StringBuilder s = new StringBuilder("");
		long c=System.currentTimeMillis();
		long c1=Runtime.getRuntime().freeMemory();
		for(int j=0;j<10000;j++){
			s.append(j);
		}
		long d=System.currentTimeMillis();
		long d1=Runtime.getRuntime().freeMemory();
		System.out.println("StringBuilder字符串拼接用时:"+(d-c));
		System.out.println("StringBuilder字符串拼接使用的内存:"+(c1-d1));
		
	}

上述代码中,测试了String类和StringBuilder类进行字符串拼接时的用时和内存占用情况。输出结果如下:

String字符串拼接用时:151
String字符串拼接使用的内存:1093896
StringBuilder字符串拼接用时:0
StringBuilder字符串拼接使用的内存:295008

可以看出使用String类进行字符串拼接时时间和空间效率都很低,因此在由频繁字符串拼接的情景下,避免使用String类,尽量使用StringBuffer类或者StringBuilder类(根据单线程和多线程决定具体使用哪一个)。

总结:

String类,StringBuffer类和StringBuilder类底层均使用了char数组存放字符序列。

String:char数组被final修饰,不可改变,修改String数组时,需要新创建String对象。

StringBuffer:线程安全,效率低。(多线程建议使用)

StringBuilder:非线程安全,效率高。(单线程建议使用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值