谈谈我对 String、StringBuilder、StringBuffer 的理解

StringBuilder、StringBuffer 和 String 一样,都是用于存储字符串的。

1、那既然有了 String ,为什么还需要他们两个呢?

原因是 String 是不可变的,它每次的字符串拼接,实际上都会 new 一个新的 String 进行接收。

2、谈谈StringBuilder、StringBuffer他们两个的联系:

我们可以知道 StringBuffer 在 1.0 的时候就发布了,那为什么还需要 StringBuilder 呢?原因是它的大部分方法都上了锁,是线程安全的,导致了效率较低!而我们有时候不需要考虑线程安全问题,追求效率!所以 StringBuilder 在 1.5 的时候就出来了!

3、StringBuilder、StringBuffer 的异同:*

不同:

  • StringBuffer 它因为追求安全,给大量方法上锁,线程安全!
  • StringBuilder 它因为追求效率,没有给方法上锁,线程不安全!

相同:内部方法和 StringBuffer 完全一致,因为都继承了 AbstractStringBuilder,底层数组都是用父类的。

4、源码浅析 String:

结论:final 修饰了底层的字符数组,故内容不可变。

5、源码浅析 StringBuilder:构造方法

观察构造方法:

    public StringBuilder() {
super(16);
} public StringBuilder(int capacity) {
super(capacity);
} public StringBuilder(String str) {
super(str.length() + 16);
append(str);
} public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}

结论:可以看出,它有一个默认的长度 16!而当传入参数是一个字符或者字符串时,它也会自动的传入参数的长度上加上 16!

6、源码浅析 StringBuilder:append 方法

    @Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
} @Override
public StringBuilder append(String str) {
super.append(str);
return this;
}

我们发现,它还是调用的父类的 append 方法,说明这个方法他并没有重写,那么 StringBuffer 也一样!

      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;
}

结论:我们可以看出,他也是可以拼接 null 的!

      private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}

然后观察,它接着进行了一个数组容量的判断,而数组的扩容,其实就是在里面实现的,我们点进去看一下!

      private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}

结论:它先是判断,当前数组容量+拼接字符 是否大于 数组长度,如果大于,则进行数组拷贝,并将底层数组的引用指向新数组!

      private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}

结论:由此可见,新数组长度扩容为原数组的 2倍+2 !

问题:那它究竟是怎么拼接字符串的呢?

sb.getChars(0, len, value, count);

进去看一下:String 的 getChars 方法

      public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
if (srcBegin < 0)
throw new StringIndexOutOfBoundsException(srcBegin);
if ((srcEnd < 0) || (srcEnd > count))
throw new StringIndexOutOfBoundsException(srcEnd);
if (srcBegin > srcEnd)
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

实际调用了一个系统类方法:arraycopy,再点进去看一下!

      public static native void arraycopy(Object src,  int  srcPos,
Object dest, int destPos,
int length);

结论:底层最终是调用的本地方法,实现了的字符数组拷贝,但由于本地方法是可以和操作系统直接打交道的,所以它的 append 字符串拼接效率会高于 String!

浅析String、StringBuilder、StringBuffer的更多相关文章

  1. 深入源码剖析String,StringBuilder,StringBuffer

    [String,StringBuffer,StringBulider] 深入源码剖析String,StringBuilder,StringBuffer [作者:高瑞林] [博客地址]http://ww ...

  2. String, StringBuilder, StringBuffer问题

    1. 区别 String为字符串常量,而StringBuilder和StringBuffer都是字符串变量,其中StringBuilder线程非安全,StringBuffer线程安全. 每次对 Str ...

  3. String StringBuilder StringBuffer区别

    String StringBuilder StringBuffer String类是final类,不可以被继承,且它的成员方法也是final方法,当一个字符串对象进行操作操作时,任何的改变不会影响到这 ...

  4. difference among String,StringBuilder,StringBuffer

    difference among String,StringBuilder,StringBuffer String常用构造函数 String(byte[] bytes) String(byte[] b ...

  5. JDK源码分析系列---String,StringBuilder,StringBuffer

    JDK源码分析系列---String,StringBuilder,StringBuffer 1.String public final class String implements java.io. ...

  6. java中String StringBuilder StringBuffer比较和效率(性能)测试

    string stringbuilder stringbuffer三者的区别 从JDK源码看,String.StringBuilder.StringBuffer都是存放在char[] 数组字符串. 简 ...

  7. 浅析String、StringBuffer、StringBuilder的区别以及性能区别

    前奏: 比较三者之间的区别在与区别他们做相同的事情的时候的区别,那就是在我们常见的拼接字符串的时候,StringBuffer.StringBuilder调用的是appende()方法,而String很 ...

  8. string,stringbuilder,stringbuffer用法

    总结:1.如果要操作少量的数据用 = String   ==================================>字符串常量2.单线程操作字符串缓冲区 下操作大量数据 = Strin ...

  9. java中string stringbuilder stringbuffer 的区别

    1. String 类 String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间. String a = "a&qu ...

  10. String,StringBuilder,StringBuffer

    (转:http://blog.csdn.net/rmn190/article/details/1492013)   String 字符串常量StringBuffer 字符串变量(线程安全)String ...

随机推荐

  1. java并发Exchanger的使用

    目录 简介 类定义 类继承 构造函数 两个主要方法 具体的例子 结语 简介 Exchanger是java 5引入的并发类,Exchanger顾名思义就是用来做交换的.这里主要是两个线程之间交换持有的对 ...

  2. centos7安装及部署zabbix监控

    一:实验环境 server.zabbix.com-------------------- 192.168.200.11 agent.zabbix.com------------------------ ...

  3. Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)

    JAVA并发包中有三个类用于同步一批线程的行为,分别是闭锁(Latch),信号灯(Semaphore)和栅栏(CyclicBarrier).本贴主要说明闭锁(Latch)和栅栏(CyclicBarri ...

  4. 回顾2016年最火热的IT技术 科技发展让人惊叹!

    编者按: 科技的发展速度总是让人们惊诧,仅从2016年来看,不仅有新涌现出来的技术和概念,还有很多甚至十年前出现的技术在今年呈现爆发性扩张.在这篇文章中,笔者将2016年最火热的IT技术尽收囊中,与各 ...

  5. Java Web:jstl处理字符串

    用法:${fn:methodName(args....)} 在使用这些函数之前必须在JSP中引入标准函数的声明<%@ taglib prefix="fn" uri=" ...

  6. 深度解析国内首个云原生数据库POLARDB的“王者荣耀”

    随着移动互联网.电子商务的高速发展,被使用最多的企业级开源数据系统MySQL面临着巨大挑战--为迎接"双11"的高并发要提前做好分库分表;用户不断激增要将读写分离才能应对每天上亿次 ...

  7. 关于fastjson在序列化成JSON串时字段增加的问题

    今天在项目中遇到控制器中返回的对象经过fastjsonMessageConverter转换后,前台收到的json中多了一个字段A的问题.而返回的这个对象中根本就没有定义这个字段A. 查了好久才发现对象 ...

  8. 你所不知道的Python | 字符串连接的秘密

    字符串连接,就是将2个或以上的字符串合并成一个,看上去连接字符串是一个非常基础的小问题,但是在Python中,我们可以用多种方式实现字符串的连接,稍有不慎就有可能因为选择不当而给程序带来性能损失. 方 ...

  9. MySQL数据库的套接字文件和pid文件

    MySQL数据库的套接字文件和pid文件 socket文件:当用Unix域套接字方式进行连接时需要的文件. pid文件:MySQL实例的进程ID文件. MySQL表结构文件:用来存放MySQL表结构定 ...

  10. nodeJS生成xlsx以及设置样式

    参考: https://www.npmjs.com/package/xlsx-style https://www.jianshu.com/p/877631e7e411 https://sheetjs. ...