谈谈我对 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. 小白也能轻松上手的Prometheus教程

    这篇文章将承接此前关于使用Prometheus配置自定义告警规则的文章.在本文中,我们将demo安装Prometheus的过程以及配置Alertmanager,使其能够在触发告警时能发送邮件,但我们将 ...

  2. KVM基本功能管理

    一.KVM基础功能管理 1.查看命令帮助 virsh -h 2.查看 KVM 的配置文件存放目录(CENTOS7.0.xml是虚拟系统实例的配置文件) ls /etc/libvirt/qemu     ...

  3. Java初学者最近三次作业的心得体会

    作为一个初学者,简单的谈一下自己的作业心得体会.如果你是完全没有接触过Java的学习,本篇博文可能会有些收获,如果你已经学习Java有一段时间了,那么可以放弃这篇文章了,因为这篇文章讲解的是基本的东西 ...

  4. 【Linux题目】第四关

    1. 如何过滤出已知当前目录下oldboy中的所有一级目录? 提示:不包含oldboy目录下面目录的子目录和隐藏目录,只要一级目录即可. 解答: ls -F|grep /   通过ls -F给目录后面 ...

  5. 【Linux网络基础】 DNS:介绍、作用、解析原理

    1. DNS是什么?   DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去+·记住能够被机器直接读 ...

  6. 解决Vue-cli3.0下scss文件编译过慢、卡顿问题

    在使用Vue-cli 3.0构建的项目中,可能存在项目编译过慢的问题,具体表现在编译时会在某一进度比如40%时停顿,等好一会儿才能够编译完成.这使得浏览器中的实时预览也会卡顿,不利于我们快速查看效果, ...

  7. python 列表加法"+"和"extend"的区别

    相同点 : "+"和"extend"都能将两个列表成员拼接到到一起 不同点 :   + : 生成的是一个新列表(id改变) extend : 是将一个列表的成员 ...

  8. 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!

    为什么80%的码农都做不了架构师?>>>   摘要: 近日,阿里云宣布高性能时间序列数据库 (High-Performance Time Series Database , 简称 H ...

  9. struts2验证码

    验证码大多是jsp,servlet写的. 我拿来主义了, 再自己完善了一下(我一直努力想要站在巨人的肩膀)   首先是页面 test.jsp <%@ page contentType=" ...

  10. 演示:配置日志发送到syslog日志服务器

    演示目标:配置网络环境中的交换机和路由器将日志发送到syslog日志服务器. 演示环境:如下图10.54所示的演示环境. 演示背景:要求部署网络中的syslog服务器,集中的收集交换机S1和路由器R1 ...