Java8 String.intern()
在 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()的理解,欢迎大家交流指正
上一篇: 函数的调用def
下一篇: golang中的 time 常用操作