谈谈我对 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制作一个简单的抽签程序

    首先需要导入import java.util.Random;才能使用随机类Random:Random生成随机数介绍:https://www.cnblogs.com/prodigal-son/p/128 ...

  2. Xapian实战(一):环境搭建 + 简介

    1. 参考资料 http://xapian.org/docs/install.html Xapian的存储系统.性能以及检索模型等 2. 安装 1) xapian # ./configure --pr ...

  3. 聊聊select, poll 和 epoll

    聊聊select, poll 和 epoll 假设项目上需要实现一个TCP的客户端和服务器从而进行跨机器的数据收发,我们很可能翻阅一些资料,然后写出如下的代码. 服务端 void func(int s ...

  4. Flutter 打包Android APK 笔记与事项

    获取一个KEY 首先要获取 你的 打包应用的一个 key ,这一步其实和 在AndroidStudio 上打包 APK 一样,都是要注册一个本地的 key,key 其实也就是 jks文件啦. 如果已经 ...

  5. 最长递增子序列(Longest increasing subsequence)

    问题定义: 给定一个长度为N的数组A,找出一个最长的单调递增子序列(不要求连续). 这道题共3种解法. 1. 动态规划 动态规划的核心是状态的定义和状态转移方程.定义lis(i),表示前i个数中以A[ ...

  6. 内存迟迟下不去,可能你就差一个GC.Collect

    一:背景 1. 讲故事 我们有一家top级的淘品牌店铺,为了后续的加速计算,在程序启动的时候灌入她家的核心数据到内存中,灌入完成后内存高达100G,虽然云上的机器内存有256G,然被这么划掉一半看着还 ...

  7. async与await----js的异步处理

    async与await----js的异步处理 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 之前写代码遇到一个问题,返回 ...

  8. java读源码 之 queue源码分析(PriorityQueue,附图)

    今天要介绍的是基础容器类(为了与并发容器类区分开来而命名的名字)中的另一个成员--PriorityQueue,它的大名叫做优先级队列,想必即使没有用过也该有所耳闻吧,什么?没..没听过?emmm... ...

  9. LeetCode寻找两个有序数组的中位数

    题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...

  10. [hdu4358]树状数组

    思路:用一个数组记录最近k次的出现位置,然后在其附近更新答案.具体见代码: #pragma comment(linker, "/STACK:10240000,10240000") ...