• 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     }
  • 相关阅读:
    CSS3实现小黄人动画
    CSS3实现时间轴效果
    CSS3实现8种Loading效果【二】
    Delphi面向对象的编程思想
    delphi 格式转换
    FindWindow和FindWindowEx函数使用
    delphi TStringList 用法详解
    ExtractFileDir 与 ExtractFilePath 的区别
    C++模板与群体数据
    C++多态性
  • 原文地址:https://www.cnblogs.com/frankyou/p/15047640.html
Copyright © 2020-2023  润新知