Java中String、StringBuffer、StringBuilder三者的区别

一、简介


      String、StringBuffer、StringBuilder三个类之间的区别主要是在两个方面:运行速度和线程安全


二、区别


1、运行速度,或者说是执行速度

      在这方面运行速度快慢为:StringBuilder > StringBuffer > String

String

      String为字符串常量是不可变的对象,因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

以下面一段代码为例:

String str = "abc";
System.out.println(str);
str = str + "de";
System.out.println(str);

输出结果为:

abc
abcde

      从输出结果看,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“abc”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“de”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。

StringBuffer

      StringBuffer是字符串变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多

      而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:

String str = "abc"+"de";
StringBuilder stringBuilder = new StringBuilder().append("abc").append("de");
System.out.println(str);
System.out.println(stringBuilder.toString());

输出结果为:

abcde
abcde

      你会很惊讶的发现,String的速度却比StringBuilder的反应速度要快很多,其实这是 JVM 的一个把戏,在 JVM 眼里,这个:

String str="abc"+"de";

其实就是:

String str = "abcde";

      所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:

String str1 = "abc";
String str2 = "de";
String str3 = str1 + str2;

      那么JVM就会像上面说的那样,不断的创建、回收对象来进行这个操作了。速度就会很慢。

StringBuilder

      StringBuilder是字符串变量,用法与StringBuffer基本相同,但是它的运行速度比StringBuffer要快,因为StringBuilder是线程不安全的,而StringBuffer是线程安全,少了同步操作,因此StringBuilder比StringBuffer要快些。


2、线程安全

在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的。

StringBuffer

Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

例如:

如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。

StringBuilder

StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。


3、总结

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

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

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


猜你喜欢

转载自blog.csdn.net/wangzhongshun/article/details/79532395