面试题:String、StringBuffer、StringBulider的区别

String、StringBuffer、StringBulider的区别
0、简单介绍:

共同点

  • 都是java.long包下的

  • 都是final类,不允许被继承

// 源码
// String类实现了Serializable、Comparable、CharSequence 
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {}

//StringBuffer类实现了Serializable、CharSequence 继承了AbstractStringBuilder
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence {}

// StringBulider类实现了Serializable、CharSequence 继承了AbstractStringBuilder
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{}

不同点:主要从执行速度和安全这两个方面来看

1、执行速度

一般情况下:StringBulider > StringBuffer > String

为什么是这个样子的呢?

因为 String 为字符常量,StringBulider和StringBuffer为字符串变量,若是使用String创建对象,这个对象是不能变的,但是后两个是变量,是可以变得。详细看下面的案例:

public static void main(String[] args) {
    String s1 = "hello";
    System.out.println(s1);
    s1 = s1 + "world";
    System.out.println(s1);
}

执行结果:

hello
helloworld

这个时候大家就要说了,这s1对象不是可以变吗?这个时候你就掉进了一个大坑里面了!

这个是由于JVM对这几行代码的优化。其实是首先创建一个s1 = “hello”,在执行到s1 = s1 + "world"的时候,JVM又创建了一个新的对象名为str,然后把原来的str值和“hello”加起来在赋值给新的str,原来的str就被JVM的垃圾回收机制给回收了,所以,实际上str没有改变,即为String对象一旦创建就不能被更改。所以String对象在创建的时候不断的新建对象和回收就对象,所以执行很慢。

看看String的源码:

// final修饰的数组,为常量,一旦赋值就不能改变,这个就是不能被修改成的原因
private final char value[];
public String() {
    this.value = "".value;
}
public String(String original) {
     // 把原字符串original切分成字符数组并赋给value[];  
    this.value = original.value;
}

再来看看StringBuffer的源码:StringBuffer和StringBulider都是继承的AbstractStringBuilder类:

// StringBuffer的构造方法
public StringBuffer() {
    super(16);
}
public StringBuffer(String str) {
    super(str.length() + 16);
    append(str);
}
// 进入super方法
AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}
char[] value;
// 这个时候就可以看出来StringBuffer类里面的value数组为普通的数组,没有被final修饰
// 而且可以通过append()方法将新字符串加入value[]末尾。这样也就改变了value[]的内容和大小了。

总结,讨论String和StringBuffer可不可变。本质上是指对象中的value[]字符数组可不可变,而不是对象引用可不可变。

看看下面这两段代码猜猜哪个更快呢?

String s1 = "hello" + "world";
StringBuffer s2 = new StringBuffer("hello").append("world");

你会发现上面的快,这是为什么呢, 这是因为第1行中的操作和String str=“abcde”;是完全一样的,所以会很快,而如果写成下面这种形式 :

String s1 = "hello";
String s2 = "world";
String s3 = s1 + s2;

执行上面这段代码,JVM就会不断的进行创建、回收对象的操作。速度就会慢。

StringBuffer和StringBuilder可谓双胞胎,StringBuilder是1.5新引入的,其前身就是StringBuffer。 StringBuilder的效率比StringBuffer稍高,这两者的方法没有很大区别。但在线程安全性方面,StringBuffer允许多线程进行字符操作。

2、线程安全

StringBuffer源码:

synchronized StringBuffer append(AbstractStringBuilder asb) {
    toStringCache = null;
    super.append(asb);
    return this;
}
public synchronized StringBuffer append(char[] str, int offset, int len) {
    toStringCache = null;
    super.append(str, offset, len);
    return this;
}
// 后面的方法省略,具体可以查看完整源码
......

StringBulider源码:

public StringBuilder append(String str) {
    super.append(str);
    return this;
}
public StringBuilder append(char[] str, int offset, int len) {
    super.append(str, offset, len);
    return this;
}
// 后面的方法省略,具体可以查看完整源码
......

观察源码你会发现: StringBuffer的很多方法都被关键字synchronized 修饰了,而StringBuilder没有。

synchornized保证了线程同步

3、总结
  • 在编译阶段就能够确定的字符串常量,完全没有必要创建String或StringBuffer对象。直接使用字符串常量的"+"连接操作效率最高。

  • StringBuffer对象的append效率要高于String对象的"+"连接操作。

  • 不停的创建对象是程序低效的一个重要原因。那么相同的字符串值能否在堆中只创建一个String对象那。显然拘留字符串能够做到这一点,除了程序中的字符串常量会被JVM自动创建拘留字符串之外,调用String的intern()方法也能做到这一点。当调用intern()时,如果常量池中已经有了当前String的值,那么返回这个常量指向拘留对象的地址。如果没有,则将String值加入常量池中,并创建一个新的拘留字符串对象。

简洁版

  • String : 会产生临时的字符串对象

  • 执行速度:StringBulider > StringBuffer > String

  • StringBuffer是线程安全的,StringBulider不是线程安全的

怎么使用

  • String:适用于少量的字符串操作的情况

  • StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

  • StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况

博客参考:

https://www.cnblogs.com/weibanggang/p/9455926.html

https://www.iteye.com/topic/522167

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值