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对象的方法,但实际上它们已经是指向了一个新建的对象。

程序例子:

69f183066ffdc18563a741cc2ee724b9.png

运行结果:

7573b22a5f9681079a401fdfefb5cc5d.png

程序分析:

e1603dfe24175cc2f1f46d7e6fd2ae84.png

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

b5de09bd7c2d7f67443b9422cf3f78f2.png

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

concat方法源码:

40d0ad48680342cf8c027632e1a217d6.png

replace方法源码:

e54b8a7abefb9dc52123e823abb4eb4c.png

为什么String设计成不可变的

字符串常量池的需要,提升效率和减少内存分配
安全性考虑,防止被意外修改(HashSet中存的值如果是可变的String,则破坏了唯一性;不可被写所以线程安全;)
作为HashMap、HashTable等hash型数据key的必要。因为不可变的设计,jvm底层很容易在缓存String对象的时候缓存其hashcode,这样在执行效率上会大大提升。

String对象真的不可变吗?

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

a31121727070a029c4b65297f2f1db56.png

运行结果:

35ecbd107e91ffe529fa21c74dc70b70.png

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

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

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值