为什么 String 是不可变的?

作者:Yujiaao

https://segmentfault.com/a/11…

我最喜欢的 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 的:

1) 想象字符串池没有使字符串不可变,它根本不可能,因为在字符串池的情况下,一个字符串对象/文字,例如 “Test” 已被许多参考变量引用,因此如果其中任何一个更改了值,其他参数将自动受到影响,即假设

String A="Test";String B="Test";

现在字符串 B 调用 "Test".toUpperCase() , 将同一个对象改为“TEST”,所以 A 也是 “TEST”,这不是期望的结果。

下图显示了如何在堆内存和字符串池中创建字符串。

为什么 String 是不可变的?

2) 字符串已被广泛用作许多 Java 类的参数,例如,为了打开网络连接,你可以将主机名和端口号作为字符串传递,你可以将数据库 URL 作为字符串传递, 以打开数据库连接,你可以通过将文件名作为参数传递给 File I/O 类来打开 Java 中的任何文件。

如果 String 不是不可变的,这将导致严重的安全威胁,我的意思是有人可以访问他有权授权的任何文件,然后可以故意或意外地更改文件名并获得对该文件的访问权限。

由于不变性,你无需担心这种威胁。这个原因也说明了,为什么 String 在 Java 中是最终的,通过使 java.lang.String final,Java设计者确保没有人覆盖 String 类的任何行为。

3) 由于 String 是不可变的,它可以安全地共享许多线程,这对于多线程编程非常重要. 并且避免了 Java 中的同步问题,不变性也使得String 实例在 Java 中是线程安全的,这意味着你不需要从外部同步 String 操作。

关于 String 的另一个要点是由截取字符串 SubString 引起的内存泄漏,这不是与线程相关的问题,但也是需要注意的。

4) 为什么 String 在 Java 中是不可变的另一个原因是允许 String 缓存其哈希码,Java 中的不可变 String 缓存其哈希码,并且不会在每次调用 String 的 hashcode 方法时重新计算,这使得它在 Java 中的 HashMap 中使用的 HashMap 键非常快。

简而言之,因为 String 是不可变的,所以没有人可以在创建后更改其内容,这保证了 String 的 hashCode 在多次调用时是相同的。

5) String 不可变的绝对最重要的原因是它被类加载机制使用,因此具有深刻和基本的安全考虑。如果 String 是可变的,加载“java.io.Writer” 的请求可能已被更改为加载 “mil.vogoon.DiskErasingWriter”. 安全性和字符串池是使字符串不可变的主要原因。

顺便说一句,上面的理由很好回答另一个Java面试问题: “为什么String在Java中是最终的”。要想是不可变的,你必须是最终的,这样你的子类不会破坏不变性。你怎么看?

推荐去我的博客阅读更多:

1. Java JVM、集合、多线程、新特性系列教程

2. Spring MVC、Spring Boot、Spring Cloud 系列教程

3. Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4. Java、后端、架构、阿里巴巴等大厂最新面试题

觉得不错,别忘了点赞+转发哦!

原文 

https://segmentfault.com/a/1190000022438164

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 为什么 String 是不可变的?

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址