Java字符串常量池是什么?为什么String可以复用?

 更新时间:2026年07月15日 14:12:11   作者:Litle_k  
为什么Java中String用==比较有时会返回true?核心在于String的复用性和不可变性,本文详解字符串常量池机制,对比直接赋值与new创建的区别,并介绍如何用StringBuilder避免内存浪费,想深入理解Java字符串?看完这篇就懂了

Java 中的 String 类型不同与其他引用类型,一般的引用类型的特性在 String 类型上你会发现并不适用。其实是 Java 对 String 类进行了包装,所以你会感觉他与其他引用类型有所不一样。

这其中就要说到他的两个特性:复用性和值不可变性。

复用性

直接赋值

String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);

上面程序运行的结果:true

这是一个令人疑惑的问题,为什么会是 true 呢?引用对象 ” == “ 比较的不是地址吗?难道它们的地址是一样的?

它们的地址是一样的,这个就是 String 的复用性。"abc"是存放在常量池中的,并且 s1 和 s2 都指向同一个地方。

当把字符串 “abc” 赋值给 s1 时,Java虚拟机会先查看常量池中是否有 “abc” 这个值,如果没有就开辟一个空间把 “abc” 存放进去然后把地址赋值给 s ,如果有就直接把 “abc” 对应的地址赋值给 s1。

同理当把字符串 “abc” 赋值给 s2 时会进行相同的操作,所以 s1 与 s2 指向的地址会是同一个。这个与Java对String的封装有关,为了减少内存的浪费,赋予了 String 复用性。

直接赋值与new关键创建对象区别

在 Java 中对 String 类型直接赋值和用 new 关键字创建对象赋值是不一样的。

String s = "abc";
String s1 = new  String ("abc");

从 Java 虚拟机出发解释上面两行代码:

  1. 第一行代码:String s = “abc”;
    把字符串 “abc” 赋值给 s 时,Java虚拟机会先查看常量池中是否有 “abc” 这个值,如果没有就开辟一个空间把“abc”存放进去然后把地址赋值给 s ,如果有就直接把 “abc” 对应的地址赋值给 s。
  2. 第二行代码:String s1 = new String (“abc”);
    new 一个对象时,Java 虚拟机会在堆中开辟一个空间,把 “abc” 存放在堆里面,再把对应的地址赋值给 s。

所以本质上这两行代码存放的空间并不一样,一个是存放在常量池中,一个是存放在堆里

值不可变性

字符串可以用两种方式赋值有一个非常重要的特征,即不可变性(immutable)。

不可变的意思是:

一旦一个字符串被创建后,它的值就不能被修改。若想改变它的值,Java虚拟机会重新开辟一个空间来存放新的值,然后指向这个地址。

  • 为了能够重用这些不变的字符串,Java使用了字符串常量池;
  • 凡是用=直接赋值的方式得到的字符串,都存储在常量池中;
  • 相同字符串内容,共用池里的一个具体字符串对象;
  • 使用new创建的字符串不适用常量池,每次都会在堆分配新内存空间

值不可变性避免了当多个对象指向同一个地址时,会出现当一个变量改变了值所有的对象都一起改变这个问题。

但是它同时带来了一个问题,就是当某个对象的值要经常发生改变时,会不断的在内存分配空间造成内存的浪费。

为了解决这个问题又出现了StringBuilder和StringBuffer这两个类,来解决这个问题。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot动态更新yml文件

    SpringBoot动态更新yml文件

    在系统运行过程中,可能由于一些配置项的简单变动需要重新打包启停项目,这对于在运行中的项目会造成数据丢失,客户操作无响应等情况发生,针对这类情况对开发框架进行升级提供yml文件实时修改更新功能,这篇文章主要介绍了SpringBoot动态更新yml文件
    2023-01-01
  • SpringBoot集成Sharding Jdbc使用复合分片的实践

    SpringBoot集成Sharding Jdbc使用复合分片的实践

    数据库分库分表中间件是采用的 apache sharding。本文主要介绍了SpringBoot集成Sharding Jdbc使用复合分片的实践,具有一定的参考价值,感兴趣的可以了解一下
    2021-09-09
  • 微信公众号开发之设置自定义菜单实例代码【java版】

    微信公众号开发之设置自定义菜单实例代码【java版】

    这篇文章主要介绍了微信公众号开发之设置自定义菜单实例代码,本实例是为了实现在管理后台实现微信菜单的添加删除管理。需要的朋友可以参考下
    2018-06-06
  • java.util.ArrayDeque类使用方法详解

    java.util.ArrayDeque类使用方法详解

    这篇文章主要介绍了java.util.ArrayDeque类使用方法,java.util.ArrayDeque类提供了可调整大小的阵列,并实现了Deque接口,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • 详解Java中Math.round()的取整规则

    详解Java中Math.round()的取整规则

    这篇文章主要介绍了详解Java中Math.round()的取整规则,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • 使用@Order控制配置类/AOP/方法/字段的加载顺序详解

    使用@Order控制配置类/AOP/方法/字段的加载顺序详解

    这篇文章主要介绍了使用@Order控制配置类/AOP/方法/字段的加载顺序详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 关于JAVA11中图片与BASE64相互转换的实现

    关于JAVA11中图片与BASE64相互转换的实现

    这篇文章主要介绍了关于JAVA11中图片与BASE64相互转换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • SpringBoot替换默认的tomcat服务器的方法

    SpringBoot替换默认的tomcat服务器的方法

    Tomcat是Apache基金下的一个轻量级的Servlet容器,支持Servlet和JSP,Tomcat具有Web服务器特有的功能,在SpringBoot框架中,我们使用最多的是Tomcat,这是SpringBoot默认的容器技术,本文给大家介绍了Spring Boot如何替换默认的tomcat服务器,需要的朋友可以参考下
    2024-08-08
  • SpringBoot中的共享Session域详解

    SpringBoot中的共享Session域详解

    这篇文章主要介绍了SpringBoot中的共享Session域详解,使用Redis解决Session共享问题的原理非常简单,就是把原本存储在不同服务器上的Session拿出来放在一个独立的服务器上,需要的朋友可以参考下
    2024-01-01
  • Java基础之常用的命令行指令

    Java基础之常用的命令行指令

    这篇文章主要介绍了Java基础之常用的命令行指令,文中有非常详细的图文示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04

最新评论