1 String a="a"; 2 String b="b"; 3 String c="a"+"b"; 4 String d=a+b; 5 String e="ab"; 6 String f=new String("ab"); 7 System.out.println(c==d); //false 8 System.out.println(c==e); //true 9 System.out.println(e==f); //false 10 System.out.println(e==f.intern()); //true 11 }
第3个false显而易见,使用new关键字就会分配一块新的内存,所以比较地址肯定是false
第1个false其实和第3个false原因是一样的,对于d让两个String对象相加就会自动的使用new关键字调构造方法
第2个为true,是因为编译的时候,会自动优化中间的那个+号,让c=“ab”,此时这个"ab"字符串在方法区的常量池是没有的,那么会将这个“ab”字符串放入常量池并返回常量池中这个“ab”字符串的引用地址,所以c指向的是常量池中的那个“ab”,而e在赋值“ab”时就会检测到常量池中已经有了这么一个字符串,所以e也指向的是常量池中的“ab”,所以c和e指向的是常量池中的同一个字符串,所以c和e相等,第2个输出结果为true。
第4个为true,f.intern()会返回常量池中和f这个字符串字符相同的字符串的引用,所以返回的引用地址就是常量池中的“ab”的地址,而e指向的就是常量池中的“ab”,所以第4个结果为true。
总结:
生成一个字符串首先判断字符串常量池是否有这么一个字符串,没有则会在常量池放入该字符串,再进行接下来的操作。
对于new String("ab")这样的一个操作会生成的对象个数可能是1,也可能是2,如果常量池中有“ab”字符串,那么就直接在堆分配一块内存,此时创建了一个对象存放“ab”,否则,首先在方法区的字符串常量池分配内存存放“ab”,然后在堆分配一块内存,存放“ab”,此时创建了两个对象。
对于String a="ab"这样的一个操作,生成的对象个数可能是0,也可能是1,原因同上。