侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

字符串池

barwe
2021-11-08 / 0 评论 / 0 点赞 / 716 阅读 / 1,491 字
温馨提示:
本文最后更新于 2022-07-14,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

在 Java 中创建 字符串对象 的方式有两种:通过字面量赋值或者通过 new 方法创建。

字符串的字面量是常量,字符串池中的字面量常量只有一个拷贝,它可以在程序任何地方被引用,以避免重复创建内容相同的字符串。通过字符串常量创建的字符串对象存放在字符串池中,通过 new 方法创建的字符串对象存放在堆中。

字符串池是 String 类维护了一块特殊的内存空间。

通过字面量赋值

String str1 = "barwe";
String str2 = "barwe";
System.out.println(str1 == str2); // true

创建 str1 时,JVM 在字符串池中找不到 “barwe” 这个常量,然后 JVM 在字符串池中创建了一个 “barwe” 常量,并将将这个常量的内存地址返回存储在变量 str1 中。

创建 str2 时,JVM 在字符串池中发现 “barwe” 常量已经存在了,JVM 直接将这个常量的内存地址返回赋值给变量 str2。

最终,变量 str1 和 str2 中存储的是字符串池中同一个 “barwe“ 常量的内存地址。 因此 str1 == str2 returns true。

通过 new 方法创建

String str3 = String.new("chin");
String str4 = String.new("chin");
System.out.println(str3 == str4); // false

创建 str3 时,字符串池没有找到常量 “chin”,因此 JVM 首先在字符串池中创建常量 “chin”,然后在 中创建一个 String 对象,然后返回这个创建的 String 对象的内存地址给变量 str3。

创建 str4 时,JVM 在字符串池中找到了对应常量,则直接在堆中创建一个 String 对象,并将其地址返回给变量 str4.

变量 str3 和 str4 指向的是堆中两个不同的 String 对象,因此 str3 == str4 returns false.

综上,存储在 字符串池 中的是 字符串常量,通过字符串常量创建的 引用变量 存储的是 字符串常量 的地址。储存在 上的是 字符串对象,通过 new 方法创建的 引用变量 存储的是 字符串对象 的地址。

所有字面量相同的 字符串常量字符串池 中都对应着同一个常量对象,所以具有相同字面量的字符串变量都相等。

这里有个非常有趣的例子:

String str1 = "hello";
String str2 = "world";
String str3 = "helloworld";
System.out.println(str3 == "helloworld"); // true
System.out.println(str3 == "hello" + "world"); // true
System.out.println(str3 == str1 + str2); // false

在第一个判断中,右边的匿名引用变量指向的字符串地址就是创建 str3 时使用的字符串池地址。

在第二个判断中,右边使用 + 连接了多个字面量,该表达式实际上是确定的,与程序运行时无关,因此该操作实际上在编译时就进行计算了,其情况与第一个判断相同。

在第三个判断中,由于引用变量 str1 和 str2 依赖于程序运行,其结果只有当程序运行到该行时才能确定。也就是说,str1 + str2 不是一个字面量,它的结果是保存在 上的,其结果是一个 字符串对象== 右边是一个匿名引用变量,指向堆上的一个字符串对象,而左边是一个指向字符串常量的变量,二者自然不相等。

0

评论区