• Java学习笔记(十五)


    字符串操作

    一、Java 中操作字符串都有哪些类?它们之间有什么区别?
    String、StringBuffer、StringBuilder

    String : final修饰,是不可变的,所以线程安全,String类的方法都是返回new String。即对String对象的任何改变都不影响到原对象,对字符串的修改操作都会生成新的对象
     

    1. //String类是final修饰,底层是用char数组来存储,也是用final修饰,不可变的类都是线程安全的
    2. public final class String
    3. implements java.io.Serializable, Comparable, CharSequence {
    4. //存放数组
    5. private final char value[];
    6. }
    • StringBuffer:线程安全的,对字符串的操作的方法都加了synchronized,保证线程安全

    • StringBuilder :线程不安全

    1. //StringBuffer与StringBuilder都继承AbstractStringBuilder,底层也是用char数组存储
    2. public final class StringBuilder
    3. extends AbstractStringBuilder
    4. implements java.io.Serializable, CharSequence {
    5. //默认数组长度16
    6. public StringBuilder() {
    7. super(16);
    8. }
    9. //如果调用有参构造,长度则为16 + 字符串长度
    10. public StringBuffer(String str) {
    11. super(str.length() + 16);
    12. append(str);
    13. }
    14. //StringBuilder与StringBuffer在appen时都调用父类的append方法
    15. @Override
    16. public StringBuilder append(String str) {
    17. super.append(str);
    18. return this;
    19. }
    20. }
    21. public final class StringBuffer
    22. extends AbstractStringBuilder
    23. implements java.io.Serializable, CharSequence {
    24. public StringBuffer() {
    25. super(16);
    26. }
    27. public StringBuffer(String str) {
    28. super(str.length() + 16);
    29. append(str);
    30. }
    31. //StringBuffer类中,所有的方法都加了synchronized,所以线程安全
    32. @Override
    33. public synchronized StringBuffer append(String str) {
    34. toStringCache = null;
    35. super.append(str);
    36. return this;
    37. }
    38. }
    39. //StringBuffer与StringBuilder的父类
    40. abstract class AbstractStringBuilder implements Appendable, CharSequence {
    41. //用char数组来存放数据,没有用final修饰,所以可变
    42. char[] value;
    43. //字符串具体的长度, char数组的长度!=字符串长度
    44. int count;
    45. //char数组的长度调用capacity方法
    46. public int capacity() {
    47. return value.length;
    48. }
    49. //每次调用append时,都产生一个新的char数组,并两次进行数组copy
    50. public AbstractStringBuilder append(String str) {
    51. if (str == null)
    52. return appendNull();
    53. int len = str.length();
    54. //数组扩容,每次复制一个新的数组
    55. ensureCapacityInternal(count + len);
    56. //将要添加的字符串复制到新数组中
    57. str.getChars(0, len, value, count);
    58. count += len;
    59. return this;
    60. }
    61. }

     二、StringBuffer与StringBuilder底层扩容机制

    1. abstract class AbstractStringBuilder implements Appendable, CharSequence {
    2. //底层扩容,调用数组copyOf方法
    3. private void ensureCapacityInternal(int minimumCapacity) {
    4. //如果append时,最小长度大于当前数组的长度,出发扩容
    5. if (minimumCapacity - value.length > 0) {
    6. value = Arrays.copyOf(value,
    7. newCapacity(minimumCapacity));
    8. }
    9. }
    10. private int newCapacity(int minCapacity) {
    11. //扩容后新数组的长度 = 老数组的长度2倍 + 2
    12. int newCapacity = (value.length << 1) + 2;
    13. if (newCapacity - minCapacity < 0) {
    14. newCapacity = minCapacity;
    15. }
    16. //不超过int最大范围
    17. return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
    18. ? hugeCapacity(minCapacity)
    19. : newCapacity;
    20. }
    21. }

     三、string类为什么是final的?

    主要是为了“效率” 和 “安全性” 的缘故。

    1、 由于String类不能被继承,所以就不会没修改,这就避免了因为继承引起的安全隐患

    2、若 String允许被继承, 由于它的高度被使用率, 可能会降低程序的性能,所以String被定义成final。

    String存放数据的char数组value用final修饰,表示该数组引用地址不可变,数组中内容可以通过反射来修改

  • 相关阅读:
    (五)正点原子STM32MP135移植——烧录
    场景图形管理-多视图与相机(3)
    通过finalshell快速在ubuntu上安装jdk1.8
    springboot整合aop,实现日志操作
    I2S总线介绍以及通信注意事项
    区块链论文一般发表在哪些地方?
    Python练习题六
    [ACTF2020 新生赛]Upload 1
    20 个提升效率的 JS 简写技巧
    从1到100这100个自然数中任取10个数,使他们的倒数和等于1。这10个数分别是多少?
  • 原文地址:https://blog.csdn.net/Rick_rui/article/details/126062732