• String,StringBuffer,StringBuilder的区别及其源码分析(一)


    String,StringBuffer,StringBuilder的区别这个问题几乎是面试必问的题,这里做了一些总结:

    1.先来分析一下这三个类之间的关系(都是通过字符数组来实现的)

      乍一看它们都是用于处理字符串的java类,而且长得也都差不多,相信肯定有人会以为StringBuffer和StringBuilder都是继承自String这个类,即认为String类是其他两个类的超类。这种想法似乎很合理,但其实是不对的,事实上StringBuffer和StringBuilder确实是继承自某个类,但是这个类并不是String,至于是哪个类呢?我i们来看一下JDK源码:

    StringBuffer类部分源码

    StringBuilder类部分源码


    String类部分源码

      看到这里,这三个类的关系基本清晰:StringBuffer和StringBuilder都继承自AbstractStringBuilder这个类,而AbstractStringBuilder和String都继承自Object这个类(Object是所有java类的超类)。所以这三个类之间的关系可以大致表示为:

     

    关于AbstractStringBuilder这个类,本人只在JDK1.8中的java.lang包下找到了,而在JDK1.6和JDK1.7中均未找到,似乎是1.8版本新加上去的,各位看官可以试着找找。

    2.String是不可变类,而StringBuffer, StringBuilder是可变类

      我们查看这三个类的源码,发现String类没有append()、delete()、insert()这三个成员方法,而StringBuffer和StringBuilder都有这些方法,这就很容易理解了(这里就不粘代码了,大家可以找源码看看)。所以我们可以归纳如下:

      String —— 字符串常量;

      StringBuffer —— 字符串变量;

      StringBuilder —— 字符串变量。

    这里再补充一点:从源代码仔细追究下去,可以发现StringBuffer和StringBuilder中的append、delete、insert这几个成员方法都是通过System类的arraycopy方法来实现的,即将原数组复制到目标数组。至于System类的定义和用法,笔者将在之后的文章进行介绍。

    3.再来说一下执行速度

      在执行速度上,String < StringBuffer < Stringbuilder 。

      3.1 String < StringBuffer

      这是因为String类是不可变的,即字符串常量,所以每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。这就会对程序运行产生很大的影响,因为当内存中的无引用对象多了以后,JVM的GC进程就会进行垃圾回收,这个过程会耗费很长一段时间,因此经常改变内容的字符串最好不要用 String类的对象。而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
      但是在某些特殊情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 运行速度是远要比 StringBuffer 快的:

      但是如果要拼接的字符串来自于不同的String对象的话,那结果就不一样了:

      这时候使用StringBuffer的运行速度更快,而这是我们编程时的大部分情况。

      3.2 StringBuffer < StringBuilder

      这个结论的原因涉及到线程安全和非线程安全,将在下一节详细介绍。

     

  • 相关阅读:
    《信号检测与估计》课程学习大纲
    测试的具体工作有哪些?
    GIT 身份验证失败问题fatal: Authentication failed for 'http:xxxxxxxxxx.git/'
    编译器的符号表管理
    node.js请求css、js静态资源页面不生效
    CF1626A Equidistant Letters 题解
    Vue父组件调用子组件事件的两种方法
    Vue子组件调用父组件事件的三种方法
    Vue高阶用法:provide / inject
    逃逸分析
  • 原文地址:https://www.cnblogs.com/Wilange/p/7570633.html
Copyright © 2020-2023  润新知