本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
竟然有其他号主问我问题,惊到我了!而且这个问题还特简单,我严重怀疑他是看不起我!
“Java 中 String 为什么设计成 final 类?为什么它有’不可变性’?”
这真是一个简单不能在简单的问题。我们先来看看 final,它就是不想让你继承。说白了,java 不想让你继承 String 类。
为什么呢?因为它是一个数据类型,就这么简单。
那为什么它有“不可变性”呢?因为它的源代码限制了它不可变。为什么要限制呢?我们先来看看什么是“不可变性”吧!
什么是不可变性?
“不可变性”可别理解错了哈。“不可变性”不是你们 YY 的那个意思。
String 很多实用的特性,比如说“不可变性”,是工程师精心设计的艺术品!艺术品易碎!用 final 就是拒绝继承,防止世界被熊孩子破坏,维护世界和平!
String 不可变很简单,如下图,给一个已有字符串"abcd"第二次赋值成"abcedl",不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。
明白了为什么不可变性后,我们再来看看为什么不可变?
上面我已经提到了源代码,那我们就从源代码说起。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** String本质是个char数组. 而且用final关键字修饰.*/ private final char value[]; ... }
从源代码中可以看出,String 类的底层 value 是个 char[] 数组,而且是用 final 修饰的。final 修饰的字段创建以后就不可改变。
哦,原来如此。。。
请注意,你们不要被这个 final 迷惑了。因为虽然 value 是不可变,也只是 value 这个引用地址不可变。挡不住 Array 数组是可变的事实。Array 的数据结构看下图:
也就是说 Array 变量只是 stack 上的一个引用,数组的本体结构在 heap 堆。String 类里的 value 用 final 修饰,只是说 stack 里的这个叫 value 的引用地址不可变。没有说堆里 array 本身数据不可变。
还不明白?那我们就一起来看个例子吧。
final int[] value={1,2,3} int[] xttblog = {4,5,6}; value = xttblog; //编译器报错,final 不可变
value 用 final 修饰,编译器不允许我把 value 指向堆区另一个地址。但如果我直接对数组元素动手,分分钟搞定。
final int[] value = {1,2,3}; value [2] = 100; //这时候数组里已经是 {1,2,100} //或者更粗暴的反射直接改 final int[] array={1,2,3}; Array.set(array,2,100); //数组也被改成{1,2,100}
所以 String 的不可变,最关键的原因是因为 SUN 公司的工程师,在设计 String 的方法时,并没有主动去修改 Array 里的元素,没有暴露内部成员字段。
说白了,SUN 就是让 String 设计成一个数据类型。
private final char value[] 这一句里,private 的私有访问权限的作用都比 final 大。而且设计师还很小心地把整个 String 设成 final 禁止继承,避免被其他人继承后破坏。所以 String 是不可变的关键都在底层的实现,而不是一个 final。别只被这一个 final 给迷惑了!
也有人讲到了 immutable 和 mutable 原则。其实呢?回答这个问题还是要回到 java 设计 String 的初衷上来。
至于为什么要让 String 设计成不可变的,那是因为安全性。不可变的好处就是为了安全,具体我们下篇文章再说!
参考资料
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » Java 中 String 为什么设计成 final 类?为什么它有“不可变性”?