关于Java中String类的不可变

学习java可变数据类型和不可变数据类型时,一定会了解到String类是不可变的

但是我们经常使用这样的方式来“改变”String。

String a = "abc";
a + = "123";

//或者

String b = "efg";
b = "456";

为什么这里的String改变了呢?

原因如图所示

执行a + = "123"并不是把"abc"改变成"abc123",而是创建了一个新的对象"abc123"后,再把a的引用指向"abc123",这时候"abc"不再被引用了,后续会被回收。而b也是同理。

我们来看String类的源码

public final class String

    implements java.io.Serializable, Comparable<String>, CharSequence {

    /** The value is used for character storage. */

    private final char value[];}

其中,String类的值保存在value数组中,而这个数组被private final修饰,意味着一旦被初始化后,就不能修改其中的值。例如a = "abc"后,这个String类中value数组就保存了"abc"且不会发生变化。然而,在a + = "123"后,并不是对原有的类操作,而是创建了一个新的String类返回给a。这意味着"abc"所在的地址空间中依然保存着"abc",而在另一个空间里创建了"abc123",然后将a指向它。

但是,问题又来了。我们看到String源码中,String类是被final修饰的。很多人会疑惑,包括我自己看到这里时也会疑惑,不是说fianl修饰的引用类型一旦指向确定的对象,便不会再改变了吗?

例如我们用final修饰一个数组

private final int[] a = {1};
a[0] = 2;

这里数组指向的内存空间是固定的,所谓用final修饰后的不可变性,但是数组里面的值还可以改变,但是如果a = new int[1]就会报错。

再来看String,为什么String用final修饰,但是如上面说的指向改变了呢?

原因是,final修饰变量的时候,基础类型值不可变,引用类型引用地址不可变。但是这里的final修饰的是一个类,final修饰类的时候表示这个类不能被继承

当我们String a的时候,并没有对对象a修饰final,所以这个时候,它的引用是可以指向新的String类的。但是当我们用final修饰a时,这时候再改变就会报错。如图所示。

 希望能解答你的疑惑。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值