欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java8 String.intern()

程序员文章站 2022-06-25 19:19:58
...

在 JAVA 语言中有 8 中基本类型和一种比较特殊的类型 String 。这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念。常量池就类似一个 JAVA 系统级别提供的缓存。
在 JDK6 及以前的版本中,运行时常量池是放在永久代。在 JDK7 及之后的版本中,字符串常量池从永久代移到堆区域,而运行时常量池仍在方法区,只不过方法区的实现从永久代变成了元空间(Metaspace)

String 类型的常量池比较特殊。它的主要使用方法有两种:
1.直接使用双引号声明出来的 String 对象会直接存储在常量池中
2.如果不是用双引号声明的 String 对象,可以使用 String 提供的 intern 方法。 intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中
注意:以下所讲的常量池都指字符串常量池(常量池分为三种类型)
类文件中常量池(The Constant Pool)
运行时常量池(The Run-Time Constant Pool)
String常量池


光看这两句话在使用上还是有问题,下面配合例子讲解

1.直接用双引号创建字符串
String str1 = "test";
String str2 = "test";
//str1 == str2 ? true
System.out.println("str3 == str4 ? "+ (str1 == str2));

直接使用双引号声明出来的 String 对象常量会直接存储在常量池中
所以str2返回的是常量池中的常量"test"

2.new String 创建字符串
String str3 = new String("tony");
str1.intern();
String str4 = "tony";
//str3 == str4 ? false
System.out.println("str3 == str4 ? " + (str3 == str4));

这个new String要这么看,分成两步
s1 = “tony”;
s2 = new String(s1);
s2.intern();
s4 = “tony”
第一句如第一种情况,常量池中检查,没有,把常量"tony"放进常量池中;s2 new String必然会在jvm堆中创建了一个实例,s2.intern()从字符串常量池中查询当前字符串是否存在,存在不作处理;s4在常量池中有常量"tony",拿过来
所以结果是false

3.new String 相加
String str5 = new String("good") + new String("morning");
str5.intern();
String str6 = "goodmorning";
//str5 == str6 ? true str5 == str5.intern() ? true
System.out.println("str5 == str6 ? " + (str5 == str6) + " str5 == str5.intern() ? " + (str5 == str5.intern()));

和第二种情况不同,第一句会分别把不在常量池的"good"和"morning"两个常量加入常量池,拼接起来"goodmorning"不在常量池,str5.intern()检查常量池是否有字符串"goodmorning",没有,把引用添加到常量池中,str6检查常量池有字符串"goodmorning",返回它的引用,所以两个判断的结果都是true

4.总结

String.intern()是给不是用双引号声明的 String 对象用的,使用后
如果常量池已有该字符串
1.若是常量,返回常量
2.若是引用,返回该引用
如果没有该字符串
把引用添加到常量池中


以上是一点对string.intern()的理解,欢迎大家交流指正