【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() 方法:可以把堆内存中的字符串放到常量池里。

相关推荐
Key~美好的每一天5 分钟前
一文了解JVM的垃圾回收
java·jvm
龙雨LongYu1221 分钟前
Go执行当前package下的所有方法
开发语言·后端·golang
米饭好好吃.28 分钟前
【Go】Go MongoDB 快速入门
开发语言·mongodb·golang
By北阳31 分钟前
Go语言 vs Java语言:核心差异与适用场景解析
java·开发语言·golang
J总裁的小芒果40 分钟前
java项目发送短信--腾讯云
java·python·腾讯云
wenbin_java1 小时前
设计模式之桥接模式:原理、实现与应用
java·设计模式·桥接模式
孫治AllenSun1 小时前
【Synchronized】不同的使用场景和案例
java·开发语言·jvm
ramsey171 小时前
Jmeter-RSA加密、解密、加签、验签
java·开发语言·python
程序视点2 小时前
重磅消息!Eclipse正式上线GitHub Copilot!
java·后端·github copilot
qq_8372873962 小时前
【Mac 系统卸载 Go 语言完整指南】
开发语言·macos·golang