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

相关推荐
Chase_Mos4 小时前
Spring 必会之微服务篇(1)
java·spring·微服务
码上淘金4 小时前
【Python】Python常用控制结构详解:条件判断、遍历与循环控制
开发语言·python
Brilliant Nemo4 小时前
四、SpringMVC实战:构建高效表述层框架
开发语言·python
格林威6 小时前
Baumer工业相机堡盟工业相机的工业视觉中为什么偏爱“黑白相机”
开发语言·c++·人工智能·数码相机·计算机视觉
小林学习编程6 小时前
SpringBoot校园失物招领信息平台
java·spring boot·后端
撸码到无法自拔6 小时前
docker常见命令
java·spring cloud·docker·容器·eureka
橙子199110166 小时前
在 Kotlin 中什么是委托属性,简要说说其使用场景和原理
android·开发语言·kotlin
androidwork6 小时前
Kotlin Android LeakCanary内存泄漏检测实战
android·开发语言·kotlin
heart000_16 小时前
IDEA 插件推荐:提升编程效率
java·ide·intellij-idea
学地理的小胖砸7 小时前
【Python 基础语法】
开发语言·python