一:什么是不可变对象?

java语言要求我们需要遵守以下5条规则

* 类内部所有的字段都是final修饰的。
* 类内部所有的字段都是私有的,也就是被private修饰。
* 类不能够被集成和拓展。
* 类不能够对外提供那些能够修改内部状态的方法,setter方法也不行。
* 类内部的字段如果是引用,也就是说可以指向可变对象,那我们程序员不能获取这个应用
二:String如何被设计成不可变对象的

* 疑惑一

在文章一开始我们就说了,String对象是不可变的,这里a=张三,然后a=李四,这符合String的不可变性嘛?答案是当然符合。

从上面这张图我们可以看到,在第一次String
a="张三"的时候,在堆中创建了同一个对象“张三”。后来我们在执行a="李四"的时候再内存中又创建了一个对象“李四”。也就是说我们的a仅仅只是改变了引用a指向的地址而已

  2.源码解释疑惑

上面最主要的是两个字段:value和hash。我们在这里主要是看value数组,hash和主题无关所以这里不再讲解了,我有专门的文章介绍hash。

我们的String对象其实在内部就是一个个字符然后存储在这个value数组里面的。但是value对外没有setValue的方法,所以整个String对象在外部看起来就是不可变的。我们画一张图解释一下上面的疑惑

现在明白了吧,也就是说真正改变引用的是value,因为value也是一个数组引用。这也可以很方便的解释下一个疑惑问题了。

   3、疑惑二

既然我们的String是不可变的,好像内部还有很多substring, replace,
replaceAll这些操作的方法。好像都是对String对象改变了,解释起来也很简单,我们每次的replace这些操作,其实就是在堆内存中创建了一个新的对象。然后我们的value指向不同的对象罢了。

面试的时候我们只是解释上面的原因其实不是那么尽善尽美,想要更好的去加薪去装逼,我们还需更进一步回答。

三、有什么办法能够改变String

既然有这个标题。那肯定就是有办法的,别忘了我们的反射机制,在通常情况下,他可以做出一些违反语言设计原则的事情。这也是一个技巧,每当面试官问一些违反语言设计原则的问题,你就可以拿反射来反驳他。下面我们来看一下:

我们可以通过反射来改变String。

现在我们知道它的原理以及用法,也知道可以通过反射来改变String,还有一个问题我们没有弄清楚,面试的时候你也可以反问他,来进一步提升自己的逼格。

四、JAVA语言为什么把String类型设计成不可变

这里有几个特点。

第一:在Java程序中String类型是使用最多的,这就牵扯到大量的增删改查,每次增删改差之前其实jvm需要检查一下这个String对象的安全性,就是通过hashcode,当设计成不可变对象时候,就保证了每次增删改查的hashcode的唯一性,也就可以放心的操作。

第二:网络连接地址URL,文件路径path通常情况下都是以String类型保存,
假若String不是固定不变的,将会引起各种安全隐患。就好比我们的密码不能以String的类型保存,,如果你将密码以明文的形式保存成字符串,那么它将一直留在内存中,直到垃圾收集器把它清除。而由于字符串被放在字符串缓冲池中以方便重复使用,所以它就可能在内存中被保留很长时间,而这将导致安全隐患

第三:字符串值是被保留在常量池中的,也就是说假若字符串对象允许改变,那么将会导致各种逻辑错误

OK,以上就是String类型对象不可变的原因

 

 

 

 

 

 

 

 

技术
©2019-2020 Toolsou All rights reserved,
继承jpa Repository 写自定义方法查询Java分布式系统高并发解决方案小结Hackbar 使用教程JQ get请求 拼接 url 参数 (查询条件)一元线性回归与多元线性回归理论及公式推导Vue 中获取下拉框的文本及选项值(精华)2020年6月26日 C#类库 文件读写操作帮助类Vue页面跳转传递参数及接收(精华)2020年6月26日 C#类库 日志帮助类keras从dataframe中读取数据并进行数据增强进行训练(分类+分割)