java string不可变_Java中的String为什么是不可变的?

String的不可变指的是String内部是使用一个被final修饰char数组value存储字符串的值

数组value的值在对象构造的时候就已经进行了赋值

String不提供方法对数组value中的值进行修改

String中需要对value进行修改的方法(例如replace)则是直接返回一个新的String对象

所以String是不可变的。

String是如何实现其对象不可变?

我们来看一下String类的两个主要成员变量,其中value指向的是一个字符串数组,字符串中的字符就是用这个value变量存储起来的,并且用final修饰,也就是说value一旦赋予初始值之后,value指向的地址就不能再改变了。虽然value指向的数组是可以改变的,但是String也没有提供相应的方法让我们去修改value指向的数组的元素。然而在StringBuilder中是提供了响应的方法让我们去修改value指向的数组的元素,这也是StringBuilder的字符串序列可变的原因。

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

private final char value[];

/** Cache the hash code for the string */

private int hash; // Default to 0

String使用中有一些看似可以改变String对象的方法,但实际上它们已经是指向了一个新建的对象。

程序例子:

运行结果:

程序分析:

str1+=str2实际上是执行了str1=(new StringBuilder()).append(str2).toString();前后实际额外产生了一个StringBuilder与一个helloworld的字符串常量。str1执行+=前后内存的示意图如下所示:

上面使用了String类的concat与replace方法,执行这两个操作不会对原来的对象产生影响,他们会返回一个全新的对象。我们可以来看一下这两个方法的源码。

concat方法源码:

replace方法源码:

为什么String设计成不可变的

字符串常量池的需要,提升效率和减少内存分配

安全性考虑,防止被意外修改(HashSet中存的值如果是可变的String,则破坏了唯一性;不可被写所以线程安全;)

作为HashMap、HashTable等hash型数据key的必要。因为不可变的设计,jvm底层很容易在缓存String对象的时候缓存其hashcode,这样在执行效率上会大大提升。

String对象真的不可变吗?

虽然value是final修饰的,只是说明value不能再重新指向其他的引用。但是value指向的数组可以改变,一般情况下我们是没有办法访问到这个value指向的数组的元素。但是,通过反射可以反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。

运行结果:

修改前的str:Hello World 修改前的str的内存地址1922154895

修改后的str:Hel?o World 修改前的str的内存地址1922154895

可以看到str的字符串序列已经被改变了,但是str的内存地址还是没有改变。

----------------------------------------------------------------------------------------------

以上内容来源于网络,自学已用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值