关于 String,StringBuilder,StringBuffer
关于 String,StringBuilder,StringBuffer 的讨论,已有很多文章;在这里,做一些自己的整理。
- String
String 是final类型,不可继承的类;内部存储是字符数组(char[]),也是final ,不可更改;
- /** 源码中 String 类的声明 */
- public final class String
- implements java.io.Serializable, Comparable<String>, CharSequence {
- /** The value is used for character storage. */
- private final char value[];
我们知道 final 修饰变量,只能被赋值一次,赋值成功后,不可再重新赋值。这意味怎么什么呢?先看一下下面的例子:
- public static void main(String[] args) {
- String a = "sdfsdklfjdskl1245";
- String b = "1234567489123";
- String c = a + b;
- System.out.println(c);
- }
这里声明三个字符常量,在初始化时,a 和 b 是字符数组常量,而 c 则是两个常量字符的连接;下面是反编译后的信息:
根据描述信息,c 变量是两个字符串连接的副本。(小弟知识范围有限,若上述代码解读有误,还请指正,不胜感激)
如果字符串直接拼接,又是怎样呢?
- public static void main(String[] args) {
- String a = "this is a" + " simple " + "test";
- System.out.println(a);
- }
看看编译后的代码解析:
可以看到编译过程做了优化,这里只产生了一个变量。
所以 String 字符串的拼接,关键在于字符串连接底层实现方式;字符串的实现是不可变字符数组,那拼接又是对字符数组怎样的操作呢?是数组拷贝?还是其他方式,有待考究... ...
String 字符串拼接效率低体现在什么地方呢?请看下面例子:
- @Test
- public void testString1() {
- String a = "123456";
- for (int i=0; i<10; i++) {
- a += "dfdsfdsfds";
- }
- System.out.println(a);
- }
上面代码中,我们初始化了常量 a,并且在循环里面做了多次字符串的拼接,最终 a 的指针地址指向了字符串拼接后的结果。
总结一下:
1、字符拼接过程产生了一定的字符数组;且是不可修改的。
2、每次改变字符串的值,就要重新生成一个String对象,然后将指针指向新的对象。
3、多余的对象一定程度上增加了GC的工作量。
综上,String 字符串拼接存在一定的性能消耗,但还不足以说性能低效;有比较才有优劣,再看看 StringBuilder 和 StringBuffer 内部又是做的呢?
- StringBuilder
StringBuilder 内部存储是字符数组,是可修改的;看一下父类:
- abstract class AbstractStringBuilder implements Appendable, CharSequence {
- /**
- * The value is used for character storage.
- */
- char[] value;
- /**
- * The count is the number of characters used.
- */
- int count;
添加字符串的方法是append,看看具体实现:
- public AbstractStringBuilder append(String str) {
- if (str == null)
- return appendNull();
- int len = str.length();
- ensureCapacityInternal(count + len);
- str.getChars(0, len, value, count);
- count += len;
- return this;
- }
- private void ensureCapacityInternal(int minimumCapacity) {
- // overflow-conscious code
- if (minimumCapacity - value.length > 0) {
- value = Arrays.copyOf(value,
- newCapacity(minimumCapacity));
- }
- }
- public static char[] copyOf(char[] original, int newLength) {
- char[] copy = new char[newLength];
- System.arraycopy(original, 0, copy, 0,
- Math.min(original.length, newLength));
- return copy;
- }
这里对字符数组做了拷贝,底层的数组拷贝实现方法:
- public static native void arraycopy(Object src, int srcPos,
- Object dest, int destPos,
- int length);
可以看到,底层调用 System.arraycopy 方法,而 arraycopy 方法是调用底层 C 语言实现的。
通过上面的源码,得出一些结论:
1、StringBuilder 在字符串拼接过程中,是对字符数组的修改;
2、append 方法对数组做了动态扩容;
3、最终实现是通过 System.arraycopy 调用 C 语言的方法;
与 String 相比,由于 StringBuilder 是对数组的修改、动态扩容,减少了中间对象的生成,在一定程度上性能较优。
- StringBuffer
StringBuffer 与 StringBuilder 都继承了 AbstractStringBuilder;
- public final class StringBuffer
- extends AbstractStringBuilder
- implements java.io.Serializable, CharSequence
- {
- /**
- * A cache of the last value returned by toString. Cleared
- * whenever the StringBuffer is modified.
- */
- private transient char[] toStringCache;
- @Override
- public synchronized StringBuffer append(String str) {
- toStringCache = null;
- super.append(str);
- return this;
- }
不同的是 StringBuffer 添加了同步锁,是线程安全的;
小结:
在字符串拼接上,不考虑线程安全的情况下 StringBuilder 优于 StringBuffer,StringBuffer 优于 String;StringBuffer 是线程安全的。
关于 String,StringBuilder,StringBuffer的更多相关文章
- 深入源码剖析String,StringBuilder,StringBuffer
[String,StringBuffer,StringBulider] 深入源码剖析String,StringBuilder,StringBuffer [作者:高瑞林] [博客地址]http://ww ...
- String, StringBuilder, StringBuffer问题
1. 区别 String为字符串常量,而StringBuilder和StringBuffer都是字符串变量,其中StringBuilder线程非安全,StringBuffer线程安全. 每次对 Str ...
- String StringBuilder StringBuffer区别
String StringBuilder StringBuffer String类是final类,不可以被继承,且它的成员方法也是final方法,当一个字符串对象进行操作操作时,任何的改变不会影响到这 ...
- difference among String,StringBuilder,StringBuffer
difference among String,StringBuilder,StringBuffer String常用构造函数 String(byte[] bytes) String(byte[] b ...
- JDK源码分析系列---String,StringBuilder,StringBuffer
JDK源码分析系列---String,StringBuilder,StringBuffer 1.String public final class String implements java.io. ...
- java中String StringBuilder StringBuffer比较和效率(性能)测试
string stringbuilder stringbuffer三者的区别 从JDK源码看,String.StringBuilder.StringBuffer都是存放在char[] 数组字符串. 简 ...
- string,stringbuilder,stringbuffer用法
总结:1.如果要操作少量的数据用 = String ==================================>字符串常量2.单线程操作字符串缓冲区 下操作大量数据 = Strin ...
- java中string stringbuilder stringbuffer 的区别
1. String 类 String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间. String a = "a&qu ...
- String,StringBuilder,StringBuffer
(转:http://blog.csdn.net/rmn190/article/details/1492013) String 字符串常量StringBuffer 字符串变量(线程安全)String ...
- String Stringbuilder Stringbuffer的区别
String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要性能 ...
随机推荐
- JDK1.8源码(四)——java.util.Arrays 类
java.util.Arrays 类是 JDK 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本上都是静态方法,能直接通过类名Arrays调用. 1.asList public static ...
- Spring Boot 1.4测试的改进
对Pivotal团队来说,工作上的好事情是他们拥有一个被叫做Pivotal Labs的灵活发展部门,拥有Labs团队的Lean 和 XP程序设计方法学的强大支持,例如结对编程和测试驱动开发.他们对于测 ...
- Python中列表、元组、字典增删改查基本区别
1.定义: 列表:num = ["a","b"."c"] ##定义后可增删改查 元组:num = ("a"," ...
- java中的并发工具类
在jdk的并发包里提供了几个非常有用的并发工具类.CountDownLatdch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线 ...
- 动态控制jQuery easyui datagrid工具栏显示隐藏
//隐藏第一个按钮 $('div.datagrid-toolbar a').eq(0).hide(); //隐藏第一条分隔线 $('div.datagrid-toolbar div').eq(0).h ...
- python全栈学习--day10(函数进阶)
一,引言 现在我有个问题,函数里面的变量,在函数外面能直接引用么? def func1(): m = 1 print(m) print(m) #这行报的错 报错了:NameError: name 'm ...
- selenium webdriver API
元素定位 #coding=utf-8 from selenium import webdriver from selenium.webdriver.firefox.firefox_binary imp ...
- JAVA序列化基础知识
1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保 存object states, ...
- Scrum 冲刺 第三日
Scrum 冲刺 第三日 目录 要求 项目链接 燃尽图 问题 今日任务 明日计划 成员贡献量 要求 各个成员今日完成的任务(如果完成的任务为开发或测试任务,需给出对应的Github代码签入记录截图:如 ...
- HP DL380服务器RAID信息丢失数据恢复方法和数据恢复过程分享
[数据恢复故障描述] 客户服务器属于HP品牌DL380系列,存储是由6块73GB SAS硬盘组成的RAID5,操作系统是WINDOWS 2003 SERVER,主要作为企业部门内部的文件服务器来 ...