MST

星途 面试题库

面试题:Java中字符串常量池与堆内存的关系

请描述Java字符串常量池在内存中的位置,以及它与堆内存是如何交互的。当使用字面量方式创建字符串和通过new关键字创建字符串时,它们在内存中的分配有何不同?
41.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

Java字符串常量池在内存中的位置

  1. JDK 1.6及之前:字符串常量池位于方法区(永久代)中。方法区是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
  2. JDK 1.7及之后:字符串常量池被移到了堆内存中。堆是Java虚拟机所管理的内存中最大的一块,是被所有线程共享的一块内存区域,几乎所有的对象实例以及数组都在这里分配内存。

字符串常量池与堆内存的交互

  1. 常量池引用堆对象:当在代码中使用字符串字面量时,如 String str = "hello";,首先会检查字符串常量池中是否已经存在 "hello" 这个字符串对象。如果存在,则直接返回常量池中该字符串对象的引用;如果不存在,则在堆内存中创建该字符串对象,并将其引用放入字符串常量池中。
  2. 字符串操作影响交互:对于字符串的拼接操作,如果拼接结果是编译期可知的常量,如 String s1 = "a" + "b";,在编译时就会直接拼接为 "ab",并在常量池中查找或创建该字符串对象。如果拼接操作涉及变量,如 String a = "a"; String s2 = a + "b";,在运行时会在堆中创建新的字符串对象,然后根据情况决定是否将其引用放入常量池(例如调用 intern() 方法)。

使用字面量方式创建字符串和通过 new 关键字创建字符串在内存中的分配区别

  1. 字面量方式创建:例如 String str1 = "hello";
    • 首先检查字符串常量池中是否存在 "hello" 这个字符串对象。
    • 如果存在,直接返回常量池中该字符串对象的引用,此时堆内存中不会新创建对象(除非常量池中该对象尚未创建)。
    • 如果不存在,在堆内存中创建该字符串对象,并将其引用放入字符串常量池,然后返回该引用。
  2. 通过 new 关键字创建:例如 String str2 = new String("hello");
    • 无论字符串常量池中是否存在 "hello",都会在堆内存中创建一个新的 String 对象。
    • 同时,如果常量池中不存在 "hello",还会在常量池中创建一个 "hello" 字符串对象(这里创建的对象是共享的,后续使用字面量 "hello" 会直接引用常量池中的这个对象)。而 new 创建的对象与常量池中的对象是不同的对象,只是内容相同。可以通过调用 intern() 方法将 new 创建的字符串对象的引用加入到常量池中,如果常量池中已存在相同内容的字符串,则返回常量池中的引用。