前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >String 的“不可变性”是因为 final?请别再错下去了!

String 的“不可变性”是因为 final?请别再错下去了!

作者头像
业余草
发布2019-03-11 14:06:06
5970
发布2019-03-11 14:06:06
举报
文章被收录于专栏:业余草业余草
640?wx_fmt=png
640?wx_fmt=png

竟然有其他号主问我问题,惊到我了!而且这个问题还特简单,我严重怀疑他是看不起我!

“Java 中 String 为什么设计成 final 类?为什么它有’不可变性’?”

640
640

这真是一个简单不能在简单的问题。我们先来看看 final,它就是不想让你继承。说白了,java 不想让你继承 String 类。

为什么呢?因为它是一个数据类型,就这么简单。

那为什么它有“不可变性”呢?因为它的源代码限制了它不可变。为什么要限制呢?我们先来看看什么是“不可变性”吧!

什么是不可变性?

“不可变性”可别理解错了哈。“不可变性”不是你们 YY 的那个意思。

String 很多实用的特性,比如说“不可变性”,是工程师精心设计的艺术品!艺术品易碎!用 final 就是拒绝继承,防止世界被熊孩子破坏,维护世界和平!

String 不可变很简单,如下图,给一个已有字符串"abcd"第二次赋值成"abcedl",不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。

640
640

明白了为什么不可变性后,我们再来看看为什么不可变?

上面我已经提到了源代码,那我们就从源代码说起。

640?wx_fmt=png
640?wx_fmt=png

从源代码中可以看出,String 类的底层 value 是个 char[] 数组,而且是用 final 修饰的。final 修饰的字段创建以后就不可改变。

哦,原来如此。。。

请注意,你们不要被这个 final 迷惑了。因为虽然 value 是不可变,也只是 value 这个引用地址不可变。挡不住 Array 数组是可变的事实。Array 的数据结构看下图:

640
640

也就是说 Array 变量只是 stack 上的一个引用,数组的本体结构在 heap 堆。String 类里的 value 用 final 修饰,只是说 stack 里的这个叫 value 的引用地址不可变。没有说堆里 array 本身数据不可变。

还不明白?那我们就一起来看个例子吧。

640?wx_fmt=png
640?wx_fmt=png

value 用 final 修饰,编译器不允许我把 value 指向堆区另一个地址。但如果我直接对数组元素动手,分分钟搞定。

640?wx_fmt=png
640?wx_fmt=png

所以 String 的不可变,最关键的原因是因为 SUN 公司的工程师,在设计 String 的方法时,并没有主动去修改 Array 里的元素,没有暴露内部成员字段。

说白了,SUN 就是让 String 设计成一个数据类型。

private final char value[] 这一句里,private 的私有访问权限的作用都比 final 大。而且设计师还很小心地把整个 String 设成 final 禁止继承,避免被其他人继承后破坏。所以 String 是不可变的关键都在底层的实现,而不是一个 final。别只被这一个 final 给迷惑了!

也有人讲到了 immutable 和 mutable 原则。其实呢?回答这个问题还是要回到 java 设计 String 的初衷上来。

至于为什么要让 String 设计成不可变的,那是因为安全性。不可变的好处就是为了安全,具体我们下篇文章再说!

原文地址:Java 中 String 为什么设计成 final 类?为什么它有“不可变性”?

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年02月16日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档