Java中字符串的存储
先决条件: Java中的字符串
众所周知,堆栈和堆空间都是Java虚拟机 (JVM) 的一部分。但是这些内存空间用于不同的目的。堆栈空间包含短暂的特定值,而Java运行时使用堆空间为对象和 JRE 类分配内存。在Java中,字符串存储在堆区域中。
为什么Java字符串存储在堆中,而不是堆栈中?
好吧,String是一个类, Java中的字符串被视为一个对象,因此String类的对象将存储在Heap中,而不是在堆栈区域中。让我们深入探讨这个话题。众所周知,我们可以通过两种方式创建字符串对象,即
1)通过字符串字面量
2)通过使用“新”关键字
字符串字面量是通过使用双引号创建的。例如:
String s=”Welcome”;
在这里,JVM 检查字符串常量池。如果字符串不存在,则创建一个新的字符串实例并将其放入池中,如果字符串存在,则它不会创建新对象,而是返回对同一实例的引用。存储这些字符串实例的缓存称为字符串常量池或字符串池。在Java的早期版本中,直到 JDK 6 字符串池位于PermGen (永久代)空间内。但是在 JDK 7 中,它被移到了主堆区域。
为什么字符串池从 PermGen 移动到正常堆区域?
PermGen 空间是有限的空间,默认大小仅为 64 MB。在 PermGen 空间中创建和存储太多字符串对象是一个问题。这就是字符串池被移动到更大的堆区域的原因。为了使Java内存效率更高,使用了字符串字面量的概念。
通过使用 'new' 关键字,即使字符串池中存在相同的字符串对象,JVM 也会在普通堆区域中创建一个新的字符串对象。
For example:
String a=new String(“Trident”);
让我们用一个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 的存储:
在上图中,String 存储在 String 常量池中。字符串对象引用变量存储在方法 main() 下的堆栈区域中。由于 main( ) 在堆栈区域中有一些空间。
笔记:
- Java中的所有对象都存储在堆中。对存储在堆栈区域中的对象的引用变量,或者它们可以包含在其他对象中,这些对象也将它们放在堆区域中。
- 该字符串由Java通过引用传递。
- 字符串引用变量本身不是引用。它是一个存储引用(内存地址)的变量。