【java】字符串存储的内存原理

1. 字符串是什么?

  • 字符串就是一段文字,比如 "Hello" 或者 "你好"

  • 在 Java 中,字符串是用 String 类型表示的。


2. 字符串的存储位置

  • 字符串在内存中的存储分为两个地方:

    1. 字符串常量池

      • 这是一个"共享区域",专门用来存放那些直接用双引号写的字符串,比如 "Hello"

      • 如果两个字符串的内容相同,它们会共享同一个内存空间,这样可以节省内存。

      • 例如:

        java

        复制代码
        String s1 = "Hello"; // "Hello" 被放入常量池
        String s2 = "Hello"; // s2 会复用常量池中的 "Hello"

        这里 s1s2 指向的是同一个 "Hello",所以 s1 == s2true

    2. 堆内存

      • 如果你用 new 关键字创建字符串,比如 new String("Hello"),那么这个字符串会放在堆内存中。

      • 堆内存中的字符串是独立的,即使内容相同,它们也是不同的对象。

      • 例如:

        java

        复制代码
        String s3 = new String("Hello"); // 在堆内存中创建一个新的 "Hello"

        这里 s3 是一个全新的对象,即使内容和 s1 相同,s1 == s3 也是 false


3. 字符串的不可变性

  • 字符串一旦创建,它的内容就不能被修改。

  • 比如:

    java

    复制代码
    String s = "Hello";
    s = s + " World"; // 这里并不是修改 "Hello",而是创建了一个新的字符串 "Hello World"
    • 原来的 "Hello" 还在内存中,新的 "Hello World" 是一个全新的字符串。

4. 为什么要用字符串常量池?

  • 节省内存

    • 如果有很多相同的字符串,比如 "Hello",它们可以共享同一个内存空间,而不是每个都单独存一份。
  • 提高性能

    • 因为字符串是不可变的,共享内存可以减少对象的创建和销毁,从而提高程序的运行效率。

5. intern() 方法的作用

  • 如果你有一个字符串是在堆内存中创建的(比如用 new),但你想把它放到字符串常量池里,可以用 intern() 方法。

  • 例如:

    java

    复制代码
    String s1 = new String("Hello"); // 在堆内存中创建
    String s2 = s1.intern(); // 把 "Hello" 放入常量池(如果池中没有)
    String s3 = "Hello"; // 复用常量池中的 "Hello"
    
    System.out.println(s1 == s2); // false,因为 s1 在堆内存,s2 在常量池
    System.out.println(s2 == s3); // true,因为 s2 和 s3 都指向常量池中的 "Hello"

6. 举个例子

假设你写了以下代码:

java

复制代码
String s1 = "Hello"; // "Hello" 被放入常量池
String s2 = "Hello"; // s2 复用常量池中的 "Hello"
String s3 = new String("Hello"); // 在堆内存中创建一个新的 "Hello"
String s4 = s3.intern(); // 把 s3 的内容放入常量池(如果不存在)

内存中的情况是这样的:

  • 字符串常量池

    复制代码
    +-------------------+
    | "Hello"           | <--- s1, s2, s4
    +-------------------+
  • 堆内存

    复制代码
    +-------------------+
    | "Hello"           | <--- s3
    +-------------------+

7. 总结

  • 字符串常量池:用来存放直接用双引号写的字符串,相同内容的字符串会共享内存。

  • 堆内存 :用来存放用 new 创建的字符串,每个字符串都是独立的对象。

  • 不可变性:字符串一旦创建,内容就不能修改,修改操作会创建新对象。

  • intern() 方法:可以把堆内存中的字符串放到常量池里。

相关推荐
独隅7 分钟前
IntelliJ IDEA 接入多种AI大模型插件终极指南(2026.1 企业合规版)
java·人工智能·intellij-idea
小大宇19 分钟前
Python 集成 Conda
开发语言·python·conda
还是奇怪35 分钟前
Simon Willison 用 DSPy 优化 Datasette Agent 提示词:提示工程正在变成可测试的软件工程
java·开发语言·软件工程
zfoo-framework1 小时前
1.ansible安装 2.虚拟机克隆
java
码上解惑1 小时前
从 Dify 工作流说起:常用节点怎么选、怎样组合?
java·人工智能·ai·agent·dify·智能体·spring ai
小大宇1 小时前
python flask框架 SSE流式返回、跨域、报错
开发语言·python·flask
Legendary_0082 小时前
LDR6500 设计指南:Type-C 音频快充二合一配件 PD 取电与插拔时序控制方案
c语言·开发语言·音视频
青山木2 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
柒星栈2 小时前
PHP 源码怎么加密防破解?三套方案实战指南
开发语言·php·android studio
勉灬之2 小时前
Next.js + Prisma 跨平台部署踩坑记
开发语言·javascript·ecmascript