在Java 中一共提供了StringStringBufferStringBuilder 用来表示和操作字符串,对于字符串的处理我们经常在项目中可以使用的到。了解它们底层的实现可以帮我们正确的使用这三个类,当然作为面试的高频题目,如果面试的时候如果面到了这个题目我们也就不怕了(~ . ~。

一、String

首先来讲String 类,可能很多人知道String 对象是内容不可变的,至于为什么是不可变的,我们通过源码来一探究竟。String 类被final 关键字修饰这也意味着String 类不可以被继承,其中实现了SerializableComparableCharSequence 接口,说明String 类自身可以被序列化、并且具有排序以及其他的功能。

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence

上面的信息并不能说明String 类内容是不可变的,String 底层其实是一个char 类型的数组,有关String 类的所有操作其实都是对这个数组进行操作然后进行处理的,比如下面的charAt() 方法就是根据传入的下标返回数组中对应的字符。

  /** The value is used for character storage. */private final char value[];..........public char charAt(int index) {if ((index < 0) || (index >= value.length)) {throw new StringIndexOutOfBoundsException(index);}return value[index];}

这个char 类型的数组也是被final 修饰的,因为被final 修饰的变量不可改变,这也是为什么String 类型的数据不可变。

当你定义一个String 类型的字符串时首先会检查在内存中是否存在该String类型的数据,如果存在那么定义的这个字符串对象就会直接指向内存中的对象并返回一个引用,如果不存在,那么就在内存中开辟一块空间用来存储该对象,并返回一个该对象的引用。

当对字符串进行相关的操作时,如果字符串中的数据发生变化,那么都会返回一个新的字符串的引用,也就是说在内存中原来的对象并没有被改变。

二、StringBuilderStringBuffer

我们把StringBufferStringBuilder 放在一起讲述,这两个类都继承了相同的抽象类AbstractStringBuilder ,都实现了SerializableCharSequence 接口。

StringBufferStringBuilder 类 和String 类不同的是它们两个都是内容可变的字符串,因为它们都实现了AbstractStringBuilder 抽象类。在AbstractStringBuilder 抽象类中也定义了一个char 类型的数组,当这两个类进行字符串的操作时,都会改变这个字符数组,因为它不被final 修饰,所以它们不像String 对象一样一旦被定义就不可改变。

public final class StringBufferextends AbstractStringBuilderimplements java.io.Serializable, CharSequencepublic final class StringBuilderextends AbstractStringBuilderimplements java.io.Serializable, CharSequence/*** The value is used for character storage.*/char[] value;

数组的长度是不可改变的(这也是为什么数组比集合的效率要高),那么为什么StringBufferStringBuilder 的字符串却是可以改变的呢?

我们以StringBuilder 类中的append() 为例,当StringBuilder 对象调用append() 方法时都会调用父类(AbstractStringBuilder )中的append() 方法,在AbstractStringBuilder 中进行append() 操作时都会执行ensureCapacityInternal() 方法进行内部容量担保操作,ensureCapacityInternal() 方法中调用了expandCapacity() 扩展字符数组容量的方法。在expandCapacity() 方法中实现了对原字符数组的扩容,为了大家能够充分理解源码的意思我在源码中添加了注释。

// StringBuilder 中的append 方法@Overridepublic StringBuilder append(String str) {super.append(str);return this;}//以下是AbstractStringBuilder 中的方法public AbstractStringBuilder append(String str) {if (str == null)return appendNull();int len = str.length();// count 表示原字符数组中使用的字符数,len 表示要添加的字符的长度,相加后表示新字符串的长度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)expandCapacity(minimumCapacity);}................void expandCapacity(int minimumCapacity) {int newCapacity = value.length * 2 + 2;//如果条件成立,给新字符数组的长度赋值为新字符串的长度,条件不成立时直接使用newCapacity 做为数组的长度if (newCapacity - minimumCapacity < 0)newCapacity = minimumCapacity;if (newCapacity < 0) {if (minimumCapacity < 0) // overflowthrow new OutOfMemoryError();newCapacity = Integer.MAX_VALUE;}//调用Arrays 中的方法返回指定长度的字符数组,到这里原字符数组的长度就被扩展了value = Arrays.copyOf(value, newCapacity);}

我们已经结合了源码分析了StringBufferStringBuilder 的类知道为什么这两个类的字符串是可以被扩展的,以及扩展的过程实现。

那么这两个类有什么不同呢?我们也以append() 方法为例好了。其中最大的不同就是StringBuffer 中使用的是同步的方法,它保证在并发执行的过程中能够正确的执行,但是它同样也存在着效率方面的问题,所以我们要正确的使用StringBufferStringBuilder

//StringBuffer 中的append() 方法@Overridepublic synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;}//StringBuilder 中的append() 方法
@Overridepublic StringBuilder append(String str) {super.append(str);return this;}

在这里另附一道题目:String 重载”+”,有兴趣的也可以看一看。

比较String、StringBuffer和StringBuilder相关推荐

  1. String,StringBuffer与StringBuilder的区别

    String,StringBuffer与StringBuilder的区别 String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全 ...

  2. Java中String StringBuffer和StringBuilder的区别是什么

    String StringBuffer 和 StringBuilder 的区别是什么?String 为什么是不可变的? 可变性 简单的来说:String 类中使用 final 关键字修饰字符数组来保存 ...

  3. String,StringBuffer与StringBuilder的区别??

    2019独角兽企业重金招聘Python工程师标准>>> String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全 ...

  4. String,StringBuffer和StringBuilder的区别

    一.可变性 不同于String类的不可变性,StringBuffer和StringBuilder都继承了抽象类AbstractStringBuilder,这个类用一个char数组来存储value. a ...

  5. String,StringBuffer和StringBuilder区别?

    String是字符串常量,final修饰;StringBuffer字符串变量(线程安全);StringBuilder 字符串变量(线程不安全).此外StringBuilder和StringBuffer ...

  6. String,StringBuffer与StringBuilder的区别?

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

  7. String,StringBuffer与StringBuilder的区别以及String为什么是不可变的?

    String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要 ...

  8. String StringBuffer 和 StringBuilder 的区别是什么?

    可变性: String类中使用了关键词final来修饰字符数组来保存字符串,private final char value[],所以String对象是不可变的:而StringBuffer与Strin ...

  9. String,StringBuffer与StringBuilder

    (1)如果要操作少量的数据用 String:  (2)多线程操作字符串缓冲区下操作大量数据 StringBuffer:  (3)单线程操作字符串缓冲区下操作大量数据 StringBuilder. st ...

  10. String, StringBuffer, and StringBuilder

    1.String String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁. ​ 再次给a赋值时,并不是对原来堆中实例对象进行重新赋值 ...

最新文章

  1. VC/MFC Tips
  2. Swift String字符串版本更新特性
  3. asp.net mvc 3 RTM 发布了!
  4. prometheus获取Consul上注册的服务
  5. effective python编写高质量Python代码的59个有效方法 pdf下载
  6. 告别2019,写给2020:干好技术,要把握好时光里的每一步
  7. SET ARITHABORT ON 对UI的影响
  8. 八年磨一剑,阿里云ApsaraDB for HBase2.0正式上线
  9. SpringCloud微服务:Ribbon和Feign组件,实现服务调用的负载均衡
  10. 微信小程序开发学习笔记007--微信小程序项目01
  11. PHP文件系统-文件路径操作和权限
  12. 2008年5月Windows Mobile Webcast预告
  13. 台电X80H平板安装ubantu
  14. 相关性分析和假设检验
  15. js 封装原生XMLHttpRequest
  16. 银联支付接口研究(Android端和Java服务端)
  17. linux学习的前期记录
  18. RT9193稳压芯片的电路原理图
  19. 划水小老虎的mysql学习路线
  20. Via浏览器怎么查看网页源码

热门文章

  1. 快速判断list是否为空
  2. Oracle——Oracle 实现类似 select top n 语句
  3. Vue 4.0——Vue与Bootstrap整合解决方案
  4. Connect Three
  5. android返回键方法,Android按返回键(后退键)Back键事件捕获的两种方法
  6. c语言垂直制表的作用,c语言中“\”的用途
  7. 2021版IDEA用Maven创建web项目
  8. 【mybatis源码系列1】 二级缓存
  9. redis - 基础
  10. 【2020年第12届全国大学生数学竞赛——资源分享 】【1~11届省赛决赛考题及题解(数学类、非数学类)、推荐学习网址、复习备考书籍推荐】