Java String 类的不可变性

蔚落 2023-10-09 12:58 108阅读 0赞

文章目录

    1. String 不可变的性质
      • 1.1 String 对象连接
      • 1.2 String 不可变实现
    1. String 不可变的目的

1. String 不可变的性质

如我们所知,String 对象通常被存在字符串常量池中,一旦一个 String 对象被创建出来,它就无法被修改。对 String 对象的所有修改操作其实都没有改变字符串本身的值,而是返回一个新的 String 对象

1.1 String 对象连接

从源码来看,String 的连接其实正如我们所知道的,不是在原 String 对象上添加字符串,而是将原字符串内容取出,重新组装一个 String 对象返回

  1. public String concat(String str) {
  2. int otherLen = str.length();
  3. if (otherLen == 0) {
  4. return this;
  5. }
  6. int len = value.length;
  7. char buf[] = Arrays.copyOf(value, len + otherLen);
  8. str.getChars(buf, len);
  9. return new String(buf, true);
  10. }

在这里插入图片描述

1.2 String 不可变实现

String 不可变性质主要是依靠 final 关键字实现,源码的类声明和真正起到存储作用的字符数组的声明都使用到了 final

  1. public final class String
  2. implements java.io.Serializable, Comparable<String>, CharSequence {
  3. /** The value is used for character storage. */
  4. private final char value[];
  5. ......
  6. }

另外可以看到,源码中对于字符数组 value 的操作都是通过深拷贝来完成的。赋值时是将传入数组保存的元素复制再写入 value 数组,读取时是将 value 数组的值取出再返回一个新的数组,保证了 value 数组的引用不会被外部持有。具体可参考 如何设计一个不可变类

  1. // 赋值
  2. public String(char value[]) {
  3. this.value = Arrays.copyOf(value, value.length);
  4. }
  5. // 读取
  6. public char[] toCharArray() {
  7. // Cannot use Arrays.copyOf because of class initialization order issues
  8. char result[] = new char[value.length];
  9. System.arraycopy(value, 0, result, 0, value.length);
  10. return result;
  11. }

2. String 不可变的目的

String 对象不可变其实具有多方面的原因,主要的考虑如下:

  1. 字符串常量池的实现
    只有当字符串是不可变的,字符串池才可能正确实现。字符串池的实现可以在运行时节约很多内存,因为不同的 字符串变量 可以指向池中的同一个字符串,避免了多个相同字符串对象的创建。如果字符串可变的话,当两个引用指向同一个字符串时,对其中一个做修改就会影响另外一个

在这里插入图片描述

  1. 安全性
    如果字符串是可变的,那么会引起很严重的安全问题。String 被广泛地充当参数使用,如网络连接、打开文件,甚至是类加载等操作。如果字符串可变,那么这些操作可能导致安全问题。比如某个方法使用字符串作为参数进行连接操作的时候,它认为自己已经连接到某台机器,但是实际上并没有(其他引用同一 String 对象的值修改会导致该连接中的字符串内容改变),这样就会对程序造成不可知的破坏
  2. 线程安全
    当字符串不可变时,天然就是多线程安全的,因为同一个字符串实例可以被多个线程共享,不用因为线程安全问题而使用同步
  3. 效率优化
    如果字符串是不可变的,在它创建的时候 hashcode 就可以被缓存,不需要重新计算。这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象

    1. /** Cache the hash code for the string */
    2. private int hash; // Default to 0

发表评论

表情:
评论列表 (有 0 条评论,108人围观)

还没有评论,来说两句吧...

相关阅读

    相关 String可变性

    什么是不可变类? > 这样理解: > 一个对象在创建完成后,不能去改变它的状态,不能改变它的成员变量(如果成员变量包含基本数据类型,那么这个基本数据类型的值不能改变;