String为什么设计成不可变

缺乏、安全感 2024-02-17 11:19 111阅读 0赞

String为什么设计成不可变

  • char数组的封装
  • 具体设计
      1. final关键字修饰字符数组
      1. private关键字修饰
      1. 没有提供操作原数组的方法
      1. final修饰String类型杜绝子类覆盖
  • 设计原因
      1. 帮助字符串常量池发挥作用
      1. 有助于哈希码的计算缓存
      1. 保证线程安全避免被修改

char数组的封装

C语言中就是用的char数组来表示的字符串,在Java的一切皆对象世界中,将char数组进行了封装,用String类型来表达字符串。

具体设计

点开String的源码就能发现char数组的身影,可以看到char数组被final关键字修饰,并且是私有成员变量。
在这里插入图片描述

1. final关键字修饰字符数组

在这里插入图片描述
单纯的字符数组被final关键字修饰,所以不可变。这个说法不准确。因为被final只代表它不可指向新的数组,又不能代表数组本身的数据不可被改变。

2. private关键字修饰

真正不可变的原因是因为它还被private修饰了。
在这里插入图片描述

3. 没有提供操作原数组的方法

并且String没有暴露和提供任何修改字符数组的方法。
在这里插入图片描述
一些字符串操作都是返回的新String对象,绝对不会影响原数据。获取其底层字符数组时,都是复制一个新数组进行返回。原数组也不会受到影响。
在这里插入图片描述

4. final修饰String类型杜绝子类覆盖

并且String类型还被final修饰了,代表其不可被继承。从而杜绝了子类覆盖父类行为的可能。
在这里插入图片描述

设计原因

1. 帮助字符串常量池发挥作用

首先,只有String不可变了,字符串常量池才能发挥作用。
在这里插入图片描述
用字面量创建字符串时,字符串常量池会返回已有对象的引用。如果字符串可变,那引用的值就可以随时修改,并能随时影响到其他的引用,从而数据会发生各种错误。这样常量池还谈何复用呢。
在这里插入图片描述

2. 有助于哈希码的计算缓存

然后,String不可变可以保证它的哈希码也不会变,因此计算一次哈希码后,就可以将其缓存。再用到时就无需计算了,性能更高。
在这里插入图片描述
也正是由于其哈希码不会变,所以可以放心去使用和哈希计算相关的对象,比如HashMap、HashSet。如果String的哈希码会改变,那就会影响到这些对象的哈希计算,从而导致预期之外的结果。

比如你之前明明存储了一个String对象,到后面你发现找不到原对象了。

3. 保证线程安全避免被修改

最后一个很重要的原因就是不可变对象都是线程安全的。因为你不用担心当前线程使用的对象会被其他线程修改。可以发现不可变对象有诸多优点,所以Java中有许多对象都设计成了不可变,比如BigDecimal。

参考资料:【每天一个技术点】String为什么不可变,有什么好处吗

发表评论

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

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

相关阅读