在Java中,String类型的数据是通过字符串常量池来存储的。字符串常量池是Java堆内存中的一个特殊的区域,用来存储字符串常量对象。
当我们使用字符串字面量创建String对象时,JVM会首先检查字符串常量池中是否已经存在相同值的字符串对象。如果存在,则返回该对象的引用;如果不存在,则在字符串常量池中创建一个新的字符串对象,并返回该对象的引用。
例如,以下代码中的str1和str2都是指向字符串常量池中同一个字符串对象的引用:
String str1 = "hello";
String str2 = "hello";
而当使用new关键字创建String对象时,JVM会在堆内存中分配一个新的字符串对象,不管字符串常量池中是否存在相同值的字符串对象。因此,以下代码中的str3和str4指向的是堆内存中的不同的字符串对象:
String str3 = new String("hello");
String str4 = new String("hello");
需要注意的是,字符串常量池中的字符串对象是不可变的,也就是说,一旦创建了一个字符串对象,就不能再修改它的值。如果对一个字符串对象进行修改,实际上是创建了一个新的字符串对象。
为了提高字符串的比较效率,Java还提供了字符串常量池的intern()方法。调用该方法可以将一个字符串对象添加到字符串常量池中,如果字符串常量池中已经存在相同值的字符串对象,则返回该对象的引用;否则,将该对象添加到字符串常量池中,并返回该对象的引用。例如:
String str5 = new String("hello").intern();
String str6 = "hello";
System.out.println(str5 == str6); // 输出true
通过调用intern()方法,str5的值被添加到了字符串常量池中,所以str5和str6指向的是同一个字符串对象。