Java String intern() 解析

String 在 java 中是一个使用最频繁的类,也是占据内存最大的类,合理的优化 String 对象,能够节省宝贵的内存资源。java

String#intern()

在每次赋值的时候使用,若是常量池中有相同值,就会重复使用该对象,返回对象引用,这样一开始的对象就能够被回收掉。数组

例子

上一段代码优化

String s1 = "abc";
String s2 = new String("abc");
String s3 = s2.intern();

System.out.println("1:" + (s1 == s2));
System.out.println("2:" + (s2 == s3));
System.out.println("3:" + (s1 == s3));
System.out.println("================================");
String s4 = new String("1") + new String("1");
String s5 = "11";
System.out.println("4:" + (s4 == s5));
String s6 = s4.intern();
System.out.println("5:" + (s4 == s5));
System.out.println("6:" + (s5 == s6));
System.out.println("7:" + (s4 == s6));

结果是:指针

1:false
2:false
3:true
================================
4:false
5:false
6:true
7:false

解析

理解这一块的核心在于这段代码运行是分为2个阶段的,1.类加载 2.类执行code

1.类加载时(注:JDK 1.7 以后,常量池合并在堆中):对象

  • 字符串常量:在常量池中开辟一个空间,存放字符串对象
  • 字符串变量:会把new String() 中的字符串放入常量池中

2.类运行时:在堆内存中开辟一个空间存放该对象,String 类中的 char 数组引用常量池对象,返回堆内存中的地址给变量引用。内存

若是调用 intern() 方法,就会去字符串常量池中查看是否有等于该对象字符串的引用,若是有,就返回返回字符串常量池中的引用资源

额外注意 s4 动态生成的字符串
动态生成的字符串直接在堆上建立,字符串常量池没有,当调用 intern 方法获取引用时,则会去常量池中判断是否有相等的引用,若是有返回引用,若是没有则放入。字符串

intern 方法 不改版自己的指针引用,从7就能够看出,s4调用intern 后与 s6 比较,仍不相等。变量

总结

  • 非动态生成的字符串,在类加载时就已经将字符串对象放入常量池中,运行时视对象是常量仍是变量赋值:

    • 常量:直接执行常量池
    • 变量:先指向堆开辟的new 空间,堆再指向常量池
  • 动态生成的字符串,直接在堆上建立,调用 intern 方法时,会去常量池中判断,若是有返回地址,若是没有,放入,返回。

intern 方法,若是常量池中没有匹配的字符串,就将本身放入而后返回,不然返回字符串对象在常量池中的地址。

思考

为何相等 ?

String a =new String("abc").intern();
String b = new String("abc").intern(); 
if(a==b) { System.out.print("a==b");}
相关文章
相关标签/搜索