目录

String

StringBuffer

StringBuilder

字符串的修改

内部数组空间大小

字符串缓存


String

String 是 Java 语言非常基础和重要的类,提供了构造和管理字符串的各种基本逻辑。它是典型的 Immutable 类(不可变类),被声明成为 final class,所有属性也都是 final 的。也由于它的不可变性,类似拼接、裁剪字符串等动作,都会产生新的 String 对象。由于字符串操作的普遍性,所以相关操作的效率往往对应用性能有明显影响。

StringBuffer

StringBuffer 是为解决上面提到拼接产生太多中间对象的问题而提供的一个类,我们可以用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本质是一个线程安全的可修改字符序列,它保证了线程安全,也随之带来了额外的性能开销,所以除非有线程安全的需要,不然还是推荐使用它的后继者,也就是 StringBuilder。

StringBuffer 的线程安全是通过把各种修改数据的方法都加上 synchronized 关键字实现的

StringBuilder

StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 没有本质区别,但是它去掉了线程安全的部分,有效减小了开销,是绝大部分情况下进行字符串拼接的首选。

字符串的修改

String 是 Immutable 类的典型实现,原生的保证了基础线程安全,因为你无法对它内部数据进行任何修改。

StringBuffer 的线程安全是通过把各种修改数据的方法都加上 synchronized 关键字实现的,非常适合常见的线程安全类实现,不必纠结于 synchronized 性能之类的,有人说“过早优化是万恶之源”,考虑可靠性、正确性和代码可读性才是大多数应用开发最重要的因素。

为了实现修改字符序列的目的,StringBuffer 和 StringBuilder 底层都是利用可修改的(char,JDK 9 以后是 byte)数组,二者都继承了 AbstractStringBuilder,里面包含了基本操作,区别仅在于最终的方法是否加了 synchronized。

内部数组空间大小

数组空间太小,拼接的时候可能要重新创建足够大的数组,扩容会产生多重开销,因为要抛弃原有数组,创建新的(可以简单认为是倍数)数组,还要进行数据拷贝。
如果太大,又会浪费空间。

字符串缓存

把常见应用进行堆转储(Dump Heap),然后分析对象组成,会发现平均 25% 的对象是字符串,并且其中约半数是重复的。如果能避免创建重复字符串,可以有效降低内存消耗和对象创建开销。

String 在 Java 6 以后提供了 intern() 方法,目的是提示 JVM 把相应字符串缓存起来,以备重复使用。在我们创建字符串对象并调用 intern() 方法的时候,如果已经有缓存的字符串,就会返回缓存里的实例,否则将其缓存起来。一般来说,JVM 会将所有的类似“abc”这样的文本字符串,或者字符串常量之类缓存起来。
被缓存的字符串是存在 PermGen 里的,也就是“永久代”,这个空间是很有限的,也基本不会被 FullGC 之外的垃圾收集照顾到。所以,如果使用不当,OOM 就会光顾。

JDK 8 中被 MetaSpace(元数据区)替代永久代,字符串缓存被放置在堆中,而且,默认缓存大小也在不断地扩大中,从最初的 1009,到 7u40 以后被修改为 60013。

Intern 是一种显式地排重机制,但是它也有一定的副作用,因为需要开发者写代码时明确调用,一是不方便,每一个都显式调用是非常麻烦的;另外就是我们很难保证效率,应用开发阶段很难清楚地预计字符串的重复情况,有人认为这是一种污染代码的实践。

幸好在 Oracle JDK 8u20 之后,推出了一个新的特性,也就是 G1 GC 下的字符串排重。它是通过将相同数据的字符串指向同一份数据来做到的,是 JVM 底层的改变,并不需要 Java 类库做什么修改。

注意这个功能目前是默认关闭的,需要使用下面参数开启,并且记得指定使用 G1 GC:

-XX:+UseStringDeduplication

前面说到的几个方面,只是 Java 底层对字符串各种优化的一角,在运行时,字符串的一些基础操作会直接利用 JVM 内部的 Intrinsic 机制,往往运行的就是特殊优化的本地代码,而根本就不是 Java 代码生成的字节码。Intrinsic 可以简单理解为,是一种利用 native 方式 hard-coded 的逻辑,算是一种特别的内联,很多优化还是需要直接使用特定的 CPU 指令。

String、StringBuffer、StringBuilder有什么区别相关推荐

  1. StringBuffer类,StringBuffer类和String的区别、String,StringBuffer,StringBuilder之间的区别

    1.概述 StringBuffer是一个线程安全的可变序列. 2.StringBuffer与String区别 (1)StringBuffer的长度和内容都可以发生改变,String却不行 (2)Str ...

  2. Java中的String,StringBuffer,StringBuilder有什么区别?

    相信有很多同学都是经常使用String的,或者也或多或少的听说过StringBuffer,StringBuilder,那么在经常遇见的面试题中(标题),到底这三个的区别是什么呢?让我们来一探究竟! S ...

  3. String, StringBuffer, StringBuilder之间的区别

    String与StringBuffer/StringBuilder之间的主要区别 1.String对象不可变, 如果修改会重新创建一个对象, 然后把值保存进去. StringBuffer/String ...

  4. java中 String StringBuffer StringBuilder的区别

    * String类是不可变类,只要对String进行修改,都会导致新的对象生成. * StringBuffer和StringBuilder都是可变类,任何对字符串的改变都不会产生新的对象. 在实际使用 ...

  5. 116day(String,StringBuffer,StringBuilder,模拟器和虚拟机的区别,复合命题的种类)

    <2018年2月4日>[连续116天] 标题:String,StringBuffer,StringBuilder,模拟器和虚拟机的区别,复合命题的种类: 内容: A.详见http://bl ...

  6. String StringBuffer StringBuilder区别与联系

    String     StringBuffer     StringBuilder String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量 ...

  7. String StringBuffer StringBuilder的区别

    简单的事情做到极致也是一种能力. 首先,说一下目前我还没进行整理的情况下,我的理解: String 不可修改 修改后相当于又新创建创建一个字符串 比如: String a = "abc&qu ...

  8. 浅谈 Java 字符串(String, StringBuffer, StringBuilder)

    我们先要记住三者的特征: String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全) 一.定义 查看 API 会发现,String ...

  9. String, StringBuffer,StringBuilder

    String, StringBuffer,StringBuilder的区别 java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,都实现了CharSe ...

  10. `java`学习笔记(十二)`Java`--`String``StringBuffer``StringBuilder`

    Java–String&&StringBuffer&&StringBuilder 文章目录 `Java`--`String`&&`StringBuffe ...

最新文章

  1. controller不跳转页面的几个原因_光知道SpringBoot,不用thymeleaf就太不对了
  2. win32的一个售票程序,收获有非常的多
  3. C与指针课后答案与编程练习(第一章)
  4. 封装成vla函数_不知道怎么封装代码?看看这几种设计模式吧!
  5. 陀螺仪c语言算法,陀螺仪c程序.docx
  6. iOS开发打电话的功能
  7. SpringBoot中使用log4j进行日志管理
  8. SAP Spartacus里的localStorage用法
  9. 前端学习(2821):windows上配置tabber字段
  10. 【南邮操作系统实验】页面置换算法(FIFO、LRU、OPT) C++ 版
  11. 在你的网站中使用 AdSense广告
  12. 用Python做一个基于OCR的微信聊天机器人
  13. VS2017透明背景和皮肤设置
  14. JAVA对接语音验证码接口API
  15. golang runtime.Caller 学习笔记
  16. android 乐固渠道打包,安卓腾讯乐固(legutools)多渠道打包(友盟)
  17. html5游戏防止作弊,html5 canvas模拟的小球躲避小游戏
  18. 使用java实现鱼刺图
  19. 寄存器寻址和寄存器间接寻址的区别
  20. 别了,指纹打卡!今后考勤可以刷脸了

热门文章

  1. jQuery实现锚点滑动定位
  2. 朋友公司招聘1名项目经理和两名asp.net(c#)程序员
  3. python GIL 全局解释器锁详解
  4. linux环境下的TIME_WAIT和CLOSE_WAIT问题解决方法
  5. fatal: unable to access ‘https://github.com/xxx/‘: Failed to connect to 127.0.0.1 port 7890: Connect
  6. 10行python代码爬取百度热榜
  7. mqtt之C++编译
  8. Centos修改yum源为阿里源
  9. 我的世界服务器开服文件夹,详细开服教程。想要自己开服的小伙伴儿 戳这里·...
  10. 输入上标的html标签是,HTML上标sup与下标注sub标签元素