拼接操作

  1. 常量与常量的拼接结果在常量池,原理是编译期优化。
  2. 常量池中不会存在相同内容的常量。
  3. 多个字符串相加+,只要其中有一个是变量,结果就在堆中。变量拼接的原理是StringBuilder。
  4. 如果拼接的结果调用intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址。
  1. public void test1() {
  2. String s1 = "a" + "b" + "c";//编译期优化:等同于"abc"
  3. String s2 = "abc"; //"abc"一定是放在字符串常量池中,将此地址赋给s2
  4. /*
  5. * 最终.java编译成.class,再执行.class
  6. * String s1 = "abc";
  7. * String s2 = "abc"
  8. */
  9. System.out.println(s1 == s2); //true
  10. System.out.println(s1.equals(s2)); //true
  11. }
  12. public void test2() {
  13. String s1 = "javaEE";
  14. String s2 = "hadoop";
  15. String s3 = "javaEEhadoop";
  16. String s4 = "javaEE" + "hadoop";//编译期优化
  17. //如果拼接符号的前后出现了变量,则相当于在堆空间中new String(),具体的内容为拼接的结果:javaEEhadoop
  18. String s5 = s1 + "hadoop";
  19. String s6 = "javaEE" + s2;
  20. String s7 = s1 + s2;
  21. System.out.println(s3 == s4);//true
  22. System.out.println(s3 == s5);//false
  23. System.out.println(s3 == s6);//false
  24. System.out.println(s3 == s7);//false
  25. System.out.println(s5 == s6);//false
  26. System.out.println(s5 == s7);//false
  27. System.out.println(s6 == s7);//false
  28. //intern():判断字符串常量池中是否存在javaEEhadoop值,如果存在,则返回常量池中javaEEhadoop的地址;
  29. //如果字符串常量池中不存在javaEEhadoop,则在常量池中加载一份javaEEhadoop,并返回次对象的地址。
  30. String s8 = s6.intern();
  31. System.out.println(s3 == s8);//true
  32. }

intern()的使用

如果不是用双引号声明的 String 对象,可以使用 String 提供的intern方法: intern方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。

比如: String myInfo = new String("I love u").intern()
也就是说,如果在任意字符串上调用String. intern方法,那么其返回结果所指向的那个类实例,必须和直接以常量形式出现的字符串实例完全相同。因此,下列表达式的值必定是true: ("a" + "b" + "c").intern() == "abc";

通俗点讲,Interned String就是确保字符串在内存里只有一份拷贝,这样可以节约内存空间,加快字符串操作任务的执行速度。注意,这个值会被存放在字符串内部池(String Intern Pool)。

  1. public class StringIntern1 {
  2. public static void main(String[] args) {
  3. //StringIntern.java中练习的拓展:
  4. String s3 = new String("1") + new String("1");//new String("11")
  5. //执行完上一行代码以后,字符串常量池中,是否存在"11"呢?答案:不存在!!
  6. String s4 = "11";//在字符串常量池中生成对象"11"
  7. String s5 = s3.intern();
  8. System.out.println(s3 == s4);//false
  9. System.out.println(s5 == s4);//true
  10. }
  11. }

**new String("ab")**会创建几个对象,**new String("a")+new String("b")**呢?
new String("ab")会创建几个对象?看字节码,就知道是两个。

  • 一个对象是:new关键字在堆空间创建的
  • 另一个对象是:字符串常量池中的对象”ab”。 字节码指令:ldc

String拼接操作 - 图1
new String("a") + new String("b")呢?

  • 对象1:new StringBuilder()
  • 对象2: new String(“a”)
  • 对象3: 常量池中的”a”
  • 对象4: new String(“b”)
  • 对象5: 常量池中的”b”

String拼接操作 - 图2
深入剖析: StringBuilder的toString():

  • 对象6 :new String(“ab”)
  • 强调一下,toString()的调用,在字符串常量池中,没有生成”ab”

参考文档