为什么 String 是不可变的?
作者:yujiaao
我最喜欢的 java 面试问题,不好回答,但同时也非常有用。一些面试者也常问这个问题,为什么 string 在 java 中是 final
的。
字符串在 java 中是不可变的,因为 string 对象缓存在 string 池中。由于缓存的字符串在多个客户之间共享,因此始终存在风险,其中一个客户的操作会影响所有其他客户。
例如,如果一段代码将 string “test” 的值更改为 “test”,则所有其他客户也将看到该值。由于 string 对象的缓存是性能的重要保证,因此通过使 string 类不可变来避免这种风险。
同时,string 是 final 的,因此没有人可以通过扩展和覆盖行为来破坏 string 类的不变性、缓存、散列值的计算等。string 类不可变的另一个原因可能是由于 hashmap
。
由于把字符串作为 hashmap 键很受欢迎。对于键值来说,不可变性是非常的重要,以便用它们检索存储在 hashmap 中的值对象。由于 hashmap 的工作原理是散列,因此需要具有相同的值才能正常运行。如果在插入后修改了 string 的内容,可变的 string 将在插入和检索时生成两个不同的哈希码,可能会丢失 map 中的值对象。
字符串是java 非常特殊的类。我还没有看到一个没有使用 string 编写的 java 程序。这就是为什么对 string 的充分理解对于 java 开发人员来说非常重要。关注微信公众号:java技术栈,在后台回复:java,可以获取我整理的 n 篇 java 教程,都是干货。
string 是数据类型,也传输对象和中间人。这种多重角色的重要性和流行性, 也使这个问题在 java 面试中很常见。
为什么 string 在 java 中是不可变的是 java 中最常被问到的字符串访问问题之一,它首先讨论了什么是 string,java 中的 string 如何与 c 和 c++ 中的 string 不同,然后转向在java中什么是不可变对象,不可变对象有什么好处,为什么要使用它们以及应该使用哪些场景。
这个问题有时也会问:“为什么 string 在 java 中是 final 的”。钻个牛角尖,你确定是不变的吗,看这篇:java 中的 string 真的是不可变的吗?在类似的说明中,如果你正在准备java 面试,我建议你看看java编程面试公开书,这是高级和中级java程序员的优秀资源。它包含来自所有重要 java 主题的问题,包括多线程,集合,gc,jvm内部以及 spring和 hibernate 框架等。
正如我所说,这个问题可能有很多可能的答案,而 string 类的唯一设计者可以放心地回答它。我在 joshua bloch 的 effective java 书中期待一些线索,但他也没有提到它。我认为以下几点解释了为什么 string 类在 java 中是不可变的或 final 的:
- 想象字符串池没有使字符串不可变,它根本不可能,因为在字符串池的情况下,一个字符串对象/文字,例如 “test” 已被许多参考变量引用,因此如果其中任何一个更改了值,其他参数将自动受到影响,即假设
string a="test";string b="test";
现在字符串 b 调用 "test".touppercase()
, 将同一个对象改为“test”,所以 a 也是 “test”,这不是期望的结果。
下图显示了如何在堆内存和字符串池中创建字符串。
- 字符串已被广泛用作许多 java 类的参数,例如,为了打开网络连接,你可以将主机名和端口号作为字符串传递,你可以将数据库 url 作为字符串传递, 以打开数据库连接,你可以通过将文件名作为参数传递给 file i/o 类来打开 java 中的任何文件。
如果 string 不是不可变的,这将导致严重的安全威胁,我的意思是有人可以访问他有权授权的任何文件,然后可以故意或意外地更改文件名并获得对该文件的访问权限。
由于不变性,你无需担心这种威胁。这个原因也说明了,为什么 string 在 java 中是最终的,通过使 java.lang.string
final,java设计者确保没有人覆盖 string 类的任何行为。
- 由于 string 是不可变的,它可以安全地共享许多线程,这对于多线程编程非常重要. 并且避免了 java 中的同步问题,不变性也使得string 实例在 java 中是线程安全的,这意味着你不需要从外部同步 string 操作。
关于 string 的另一个要点是由截取字符串 substring 引起的内存泄漏,这不是与线程相关的问题,但也是需要注意的。
- 为什么 string 在 java 中是不可变的另一个原因是允许 string 缓存其哈希码,java 中的不可变 string 缓存其哈希码,并且不会在每次调用 string 的 hashcode 方法时重新计算,这使得它在 java 中的 hashmap 中使用的 hashmap 键非常快。
简而言之,因为 string 是不可变的,所以没有人可以在创建后更改其内容,这保证了 string 的 hashcode 在多次调用时是相同的。
- string 不可变的绝对最重要的原因是它被类加载机制使用,因此具有深刻和基本的安全考虑。如果 string 是可变的,加载“java.io.writer” 的请求可能已被更改为加载 “mil.vogoon.diskerasingwriter”. 安全性和字符串池是使字符串不可变的主要原因。
顺便说一句,上面的理由很好回答另一个java面试问题: “为什么string在java中是最终的”。要想是不可变的,你必须是最终的,这样你的子类不会破坏不变性。你怎么看?
推荐去我的博客阅读更多:
2.spring mvc、spring boot、spring cloud 系列教程
3.maven、git、eclipse、intellij idea 系列工具教程
觉得不错,别忘了点赞+转发哦!
上一篇: c# 使用NPOI进行文件导出
下一篇: 鱼咋做好吃,才能更受人们的青睐