Java string不可变原理实例解析

 更新时间:2020年04月27日 09:29:12   作者:牛顿顿的星空  
这篇文章主要介绍了Java string不可变原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

我最喜欢的 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”,这不是期望的结果。

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

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中是最终的”。要想是不可变的,你必须是最终的,这样你的子类不会破坏不变性。你怎么看?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot通过计划任务发送邮件提醒的代码详解

    SpringBoot通过计划任务发送邮件提醒的代码详解

    在实际线上项目中,有不断接受到推送方发来的数据场景,而且是不间断的发送,如果忽然间断了,应该是出问题了,需要及时检查原因,这种情况比较适合用计划任务做检查判断,出问题发邮件提醒,本文给大家介绍了SpringBoot通过计划任务发送邮件提醒,需要的朋友可以参考下
    2024-11-11
  • SpringBoot调用DeepSeek接口的实现

    SpringBoot调用DeepSeek接口的实现

    本文主要介绍了SpringBoot调用DeepSeek接口的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-02-02
  • java实现微信公众平台发送模板消息的示例代码

    java实现微信公众平台发送模板消息的示例代码

    这篇文章主要介绍了java实现微信公众平台发送模板消息的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Java使用POI从Excel读取数据并存入数据库(解决读取到空行问题)

    Java使用POI从Excel读取数据并存入数据库(解决读取到空行问题)

    有时候需要在java中读取excel文件的内容,专业的方式是使用java POI对excel进行读取,这篇文章主要给大家介绍了关于Java使用POI从Excel读取数据并存入数据库,文中介绍的办法可以解决读取到空行问题,需要的朋友可以参考下
    2023-12-12
  • SpringBoot读取外部配置文件的方法

    SpringBoot读取外部配置文件的方法

    这篇文章主要介绍了SpringBoot读取外部配置文件的方法,以端口配置为例,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • SpringBoot集成SFTP客户端实现文件上传下载实例

    SpringBoot集成SFTP客户端实现文件上传下载实例

    这篇文章主要为大家介绍了SpringBoot集成SFTP客户端实现文件上传下载实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 两种java实现二分查找的方式

    两种java实现二分查找的方式

    这篇文章主要给大家分享的是java实现二分查找的方式,二分查找是一种查询效率非常高的查找算法。又称折半查找。下面文章我们介绍了两种方法,需要的朋友可以参考一下
    2021-09-09
  • 浅谈mac下maven的安装配置与使用

    浅谈mac下maven的安装配置与使用

    这篇文章主要介绍了浅谈mac下maven的安装配置与使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • 多数据源@DS和@Transactional实战

    多数据源@DS和@Transactional实战

    这篇文章主要介绍了多数据源@DS和@Transactional实战,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • 打包部署若依(RuoYi)SpringBoot后端和Vue前端图文教程

    打包部署若依(RuoYi)SpringBoot后端和Vue前端图文教程

    若依是一个使用Spring Boot作为后端和Vue.js作为前端的全栈应用开发平台,下面这篇文章主要给大家介绍了关于打包部署若依(RuoYi)SpringBoot后端和Vue前端的相关资料,需要的朋友可以参考下
    2024-05-05

最新评论