Java中String,StringBuilder和StringBuffer的区别
来源:互联网 发布:施工进度图绘制软件 编辑:程序博客网 时间:2024/09/21 09:19
欢迎关注本人公众号
大家都知道,String对象是不可变的,不可变性会带来效率问题。为String对象重载“+”操作符时,都会自动生成一个新的String对象。
也有人说,String在上述的问题中已经会自动引入StringBuilder来解决效率问题。
为此,我在《Java编程思想》中找到了答案。
第一个小例子:
执行编译,命令:javac TestString.java
用javap来反编译上述代码,看看都发生了什么故事:
javap -c TestString
结果如下:
从上述代码中看,编译器确实创建了一个StringBuilder对象。
但是,这并不能因此就说明可以随意的使用String对象。下面又举了个例子:
反编译一下:
[linc@localhost TestString]$ javac StringAndBuilder.java
[linc@localhost TestString]$ javap -c StringAndBuilder
注意到implicit方法,从第8行到第35行构成了一个循环体。StringBuilder是在循环体内构造的,也就是说,每经过一次循环,就会创建一个新的StrinBuilder对象。
再看explicit方法,循环部分的代码更简短、简单,而且只生成了一个StrinBuilder对象。
结论:
当为一个类编写toString()方法时,如果操作比较简单,就可以信赖编译器,它会为你合理的构造最终的字符串结果。如果使用了循环,那么最好自己创建一个StringBuilder对象。
如果拿不准该用那种方式,就用javap来分析你的程序吧!
另外,linc之前还翻译了一段小文章,是讲String、StringBuffer和StringBuilder之间的区别的:http://blog.csdn.net/lincyang/article/details/6333041
------------------------------------------------------------------------------------------------------------------------------
可以证明,字符串操作是计算机程序设计中最常见的行为。
对象的引用与对象关联——初始化,例如:s = "abc";//Java语言特性,String可以用带引号的文本初始化。
更通用的初始化,创建对象,例如:s = new String("abc");——《Thinking in Java》
Java中所有的字符串文字[字符串常量]都是一个String的对象。Java中维护一个字符串常量列表(常量池,编译时决定),
存放字符创常量。当遇到字符串常量时,先检查它常量池是否存在,不存在则在堆上创建对象并将字符串常量放入常量池。
被放到字符串内部列表中的字符串对象是不会被垃圾回收的,生命周期和整个程序相同,所以如果使用不当会造成内存泄露。
String对象具有只读特性,指向它的任何引用都不可能改变它的值。不可变性带来的是效率问题。String中的+和+=是仅有的两个重载过的操作符。Java不允许程序员重载任何操作符。 由于字符串对象的大量使用(它是一个对象,一般而言对象总是在heap分配内存),Java中为了节省内存空间和运行时间(如比较字符串时,==比equals()快),在编
译阶段就把所有的字符串文字放到一个文字池(pool of literal strings,即字符串常量列表)中,而运行时文字池成为常量池的一部分。文字池的好处,就是该池中所有相同的字符串常量被合并,只占用一个空间。
StringBuilder类,对应于String类,StringBuilder具有可变性。
StringBuilder是Java SE5引入的,线程非安全的。
StringBuffer是Java SE5之前就有的线程安全的,相对来说较StringBuilder开销稍大
两者的常用操作:append(),toString(),insert(),reverse(),delete()等。
String:不可变的对象,对String对象进行改变的时候其实都等同于生成了一个新的String对象,然后将引用指向新的String对象,原String对象GC回收。
StringBuffer 字符串变量(线程安全),适用于多线程程序中,保证同步性。
StringBuilder 字符串变量(非线程安全),适用于单线程程序中,不保证同步性。简要的说, String 类和 StringBuffer/StringBuilder 类的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类进行改变的 时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成 对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。 而如果是使用 StringBuffer/StringBuilder 类则结果就不一样了,每次结果都会对 StringBuffer/StringBuilder 对象本身进行操作,而不是生成 新的对象,再改变对象引用。所以在一般情况下推荐使用 StringBuffer/StringBuilder ,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成 StringBuffer/StringBuilder 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer/StringBuilder 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
String S1 = “This is only a” + “ simple” + “ test”;
StringBuilder Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,
在 JVM 眼里,这个
String S1 = “This is only a” + “ simple” + “test”; 其实就是:
String S1 = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象
的话,速度就没那么快了,譬如:
String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;
这时候 JVM 会规规矩矩的按照原来的方式去做
在大部分情况下 StringBuffer > String
StringBuffer
Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但可以修改。虽然在任意时间点上它都包含某
种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,
而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
在大部分情况下 StringBuilder > StringBuffer
java.lang.StringBuilder
java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用
作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在
大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
0 0
- java中String、StringBuffer和StringBuilder区别
- java中string stringbuffer和stringBuilder区别
- 【Java】Java中,String、StringBuffer和StringBuilder的区别
- Java中String ,StringBuffer和StringBuilder的区别和用法
- 在Java中string和stringbuffer和stringbuilder的区别
- Java中String、StringBuilder和StringBuffer的区别
- Java中String,StringBuilder和StringBuffer的区别
- Java中String,StringBuilder和StringBuffer的区别
- java中String、StringBuffer和StringBuilder的区别
- Java中String、StringBuffer和StringBuilder的区别
- Java中String、StringBuilder和StringBuffer的简单区别
- Java中String,StringBuilder和StringBuffer的区别
- Java中String,StringBuilder和StringBuffer的区别
- Java中String,StringBuilder和StringBuffer的区别
- java中String、StringBuffer和StringBuilder的区别
- java中String和StringBuffer以及StringBuilder的区别
- Java中String,StringBuilder和StringBuffer的区别
- Java中String、StringBuilder和StringBuffer类的区别
- POJ 3348 Cows(凸包+多边形面积)
- 函数指针
- SQL第一天
- IOS-使用framework实现功能模块动态更新
- hadoop在linux系统下的集群时间同步
- Java中String,StringBuilder和StringBuffer的区别
- SQL第二天
- 解决bash:没有那个文件或目录的方法
- SQL第三天
- hdu 2137 circumgyrate the string
- Ural1225(数学)
- SQL第四天
- UVa 11110 - Equidivisions
- WPF中图形表示语法详解(Path之Data属性语法)