String为什么是不可变的?为什么要有字符串常量池?String和StringBuilder和StringBuffer

22 篇文章 0 订阅

String的相关知识点

1. 不可变字符串String类对象

  String类没有提供用于修改字符串的方法,在Java中字符串的不可修改使得String类对象被称为不可变字符串。那么String为什么不可变呐?

String s = "Hello!";
s = "GoodBye!"
System.out.println(s);//GoodBye!

在这里插入图片描述

  对象的不可变性是指对象本身的属性或者说本身的数据不会改变,将变量重新赋值,是创建了一个新对象,然后将新对象的引用赋值给了变量,之前的对象是没有受到影响的。

  从编译器中去查看String类的源码
在这里插入图片描述
在这里插入图片描述

  我们可以看到Java中char数组被进行了封装,用String类型来表达字符串。char数组被final修饰,并且是私有的成员变量。字符数组不能再指向新的数组,但是数组本身的数据可能是会被修改的。真正体现字符串的不可变性是因为这个字符数组被private所修饰了,并且String没有提供任何可以修改字符数组的方法。一些字符串的操作都是返回了新的对象,一定不会影响到原数据。在获取底层字符数组时,都是复制一个新数组进行返回,原数组也不会受到影响。同时String类还被final修饰,表示该类不可被继承,其中的方法也不可能被重写(覆盖)。

  顺带提一嘴,Arrays.copyOf(数组,数组长度)方法可以用来给数组扩容。新数组长度要是比原数组长,后面没有的就全赋值为0(基本类型数组);反之,比原数组短的话,只复制到新数组长度那么多的值。

2. String不可变的好处

  • 只有字符串不可变,字符串常量池才能发挥作用。对其进行字面量创建字符串对象时,没有便在字符串常量池中创建对象,有的话字符串常量池会返回已有对象的引用。如果字符串是可变的,引用的值就可以随时被修改并影响其他的引用,数据会产生错误。常量池就不能实现其复用功能了。

在这里插入图片描述

  • String不可变可以保证它的hashCode不会改变,计算一次hashcode之后可以将hashcode进行缓存,再次使用时就不需要计算,大大提高了使用性能。
  • hashcode的不变,可以让String类去使用和哈希计算相关的对象,比如HashMap,HashSet。
  • 不可变对象都是线程安全的,当前被使用的对象不会被其他线程进行修改。

3.字符串常量池(原理)

  使用双引号来直接创建对象,这种直接声明的方式叫做字面量。我们使用平时都了解到的方式去通过new去创建对象,即使它的字面量一致,他也是创建了多个对象,这样会导致资源的浪费,同时也占用空间。那么我们可以如何去解决这个问题呐?可以将创建的对象进行复用。比如:声明为静态常量。

private static final Person person = new Person(18);

  如果要复用多个复杂无规律的对象,又应该怎么办呐?这时可以将这些对象都放到一个容器中,需要使用时,再获取,这便是对象池
我们可以把对象池看作一个缓存区,它可以有效地避免资源的重复创建

在这里插入图片描述
  字符串常量池就是由JVM提供的用来复用对象的一个对象池。它位于堆内存中。当我们使用字面量创建字符串时,字符串常量池会将其对象引用进行保存,如果之后创建重复的字面量就会直接返回字符串常量池中的引用。有效地避免资源的重复创建。

4. String、StringBuilder和StringBuffer

  当我们对字符串进行大量操作时,就必须产生很多新的对象,这会导致性能低下。为了解决这一问题StringBuilder运营而生。

在这里插入图片描述
在这里插入图片描述  从源码我们可以看到,它继承的AbstractStringBuilder底层也是一个char数组来表示字符串,但它可被访问且可变.StringBuilder中提供了大量的方法来对字符串进行修改。
在这里插入图片描述
  当我们使用String进行字符串拼接时,他的底层会创建StringBuilder对象,并调用sb.append()方法。
  关于他们三者的具体区别可以看我另一篇文章String和StringBuilder和StringBuffer的详细解析

三者使用场景

类型特点使用场景
String不可变,线程安全操作少量数据或不需要操作数据
StringBuilder可变,线程不安全需要频繁操作数据且不用考虑线程安全
StringBuffer可变,线程安全,性能较低需要频繁操作数据且需要考虑线程安全

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值