Java 字符串常量池 及 intern 方法的使用

 参考这篇文章:深入解析String#intern - 美团技术团队 (meituan.com)

jdk7 版本对 intern 操作和常量池都做了一定的修改,主要包括2点:

  1. 将String常量池 从 Perm 区移动到了 Java Heap区
  2. String#intern 方法时,如果存在堆中的对象,会直接保存堆中对象的引用,而不会重新创建对象

下面做一个测试:

 1 public static void main(String[] args) {
 2 
 3         /*
 4          * new String("a") + new String("b") 在堆和字符串常量池一共传创建了 5 个对象,分别为:
 5          * 堆:"a"、"b"、"ab" + 字符串常量池:"a"、"b"
 6          * 但 str1 是堆中 "ab" 对象的引用,并非字符串常量池 "ab" 对象的引用
 7          * str1.intern() 实际是返回了字符串常量池 "ab" 对象的引用
 8          * str3.intern() 也是返回了字符串常量池 "ab" 对象的引用
 9          */
10 
11         // 返回堆中 "ab" 对象的引用
12         String str1 = new String("a") + new String("b");
13         // 在字符串常量池中生成 "ab" 对象并返回其引用
14         String str2 = "ab";
15         // 返回堆中新生成的 "ab" 对象的引用
16         String str3 = new String("a") + new String("b");
17         // false, str1.intern() 返回字符串常量池中的引用,str1为堆中的引用,二者不是同一个内存地址
18         System.out.println(str1.intern() == str1);
19         // true, str1.intern() 和 str2 都是堆中同一个对象 "ab" 的引用
20         System.out.println(str1.intern() == str2);
21         // false, str1 和 str3 分别指向了堆中 2 个不同的 "ab" 对象
22         System.out.println(str1 == str3);
23         // true, str1.intern() 和 str3.intern() 都是字符串常量池中同一个对象 "ab" 的引用
24         System.out.println(str1.intern() == str3.intern());
25     }

 另一个测试:

 1     public static void main(String[] args) {
 2         /*
 3          * 直接使用双引号声明出来的 String 对象会直接存储在常量池中,此时堆中生成一个 ”1“ 对象,字符串常量池中也生成一个 ”1“ 对象
 4          * 返回的是堆中 ”1“ 对象的引用
 5          */
 6         String s = new String("1");
 7         // 此时字符串常量池中已经存在 ”1“ 对象了,所以不会有堆中此对象引用拷贝的操作了
 8         s.intern();
 9         // 此时字符串常量池中已经存在 ”1“ 对象了,直接返回字符串常量池中此对象的引用
10         String s2 = "1";
11         // fasle, s 为堆中对象的引用,s2 为字符串常量池中对象的引用,二者内存地址不一样
12         System.out.println(s == s2);
13 
14         // 在堆中生成 3 个对象,分别为 ”1“、”1“、”11“ 并返回堆中对象 ”11“ 的引用,此时常量池中是没有 ”11“ 对象的
15         String s3 = new String("1") + new String("1");
16         // 把 s3 的引用拷贝到字符串常量池中
17         s3.intern();
18         // 直接返回字符串常量池中 s3 的引用
19         String s4 = "11";
20         // true,s3 和 s4 均为字符串常量池中的同一个内存地址
21         System.out.println(s3 == s4);
22     }

 

posted @ 2021-07-23 10:16  FrankYou  阅读(132)  评论(0编辑  收藏  举报