📜  Java中字符串的存储

📅  最后修改于: 2022-05-13 01:55:23.942000             🧑  作者: Mango

Java中字符串的存储

先决条件: Java中的字符串

众所周知,堆栈和堆空间都是Java虚拟机 (JVM) 的一部分。但是这些内存空间用于不同的目的。堆栈空间包含短暂的特定值,而Java运行时使用堆空间为对象和 JRE 类分配内存。在Java中,字符串存储在堆区域中。

为什么Java字符串存储在堆中而不是堆栈中?

好吧,String是一个类, Java中的字符串被视为一个对象,因此String类的对象将存储在Heap中,而不是在堆栈区域中。让我们深入探讨这个话题。众所周知,我们可以通过两种方式创建字符串对象,即

1)通过字符串字面量

2)通过使用“新”关键字

字符串字面量是通过使用双引号创建的。例如:

在这里,JVM 检查字符串常量池。如果字符串不存在,则创建一个新的字符串实例并将其放入池中,如果字符串存在,则它不会创建新对象,而是返回对同一实例的引用。存储这些字符串实例的缓存称为字符串常量池或字符串池。在Java的早期版本中,直到 JDK 6 字符串池位于PermGen (永久代)空间内。但是在 JDK 7 中,它被移到了主堆区域。

为什么字符串池从 PermGen 移动到正常堆区域?

PermGen 空间是有限的空间,默认大小仅为 64 MB。在 PermGen 空间中创建和存储太多字符串对象是一个问题。这就是字符串池被移动到更大的堆区域的原因。为了使Java内存效率更高,使用了字符串字面量的概念。

通过使用 'new' 关键字,即使字符串池中存在相同的字符串对象,JVM 也会在普通堆区域中创建一个新的字符串对象。

让我们用一个Java程序来看看这个概念,并可视化实际的 JVM 内存结构:

Java
import java.io.*;
  
class GFG {
    public static void main(String[] args)
    {
        
          // String created using String literal
        String s1 = "TAT"; 
        String s2 = "TAT";
        
          // String created using 'new' keyword
        String s3 = new String("TAT"); 
        String s4 = new String("TAT");
        
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
    }
}


输出:

TAT
TAT
TAT
TAT

下图说明了 String 的存储:

Java中字符串的存储

在上图中,String 存储在 String 常量池中。字符串对象引用变量存储在方法 main() 下的堆栈区域中。由于 main( ) 在堆栈区域中有一些空间。

笔记:

  • Java中的所有对象都存储在堆中。对存储在堆栈区域中的对象的引用变量,或者它们可以包含在其他对象中,这些对象也将它们放在堆区域中。
  • 该字符串由Java通过引用传递。
  • 字符串引用变量本身不是引用。它是一个存储引用(内存地址)的变量。