String a=
"a"
+
"b"
+
"c" 创建了几个对象
这个问题涉及到了字符串常量池和字符串拼接
String a="a"+"b"+"c"
通过编译器优化后,得到的效果是
String a="abc"
Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";
另一种就是使用new这种标准的构造对象的方法,如String str = new String("droid");
这两种方式我们在代码编写时都经常使用,尤其是字面量的方式。然而这两种实现其实存在着一些性能和内存占用的差别。这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池。
当我们使用了new来构造字符串对象的时候,不管字符串常量池中有没有相同内容的对象,新的字符串对象都会创建(在堆中)。
堆:存放所有new出来的对象;
栈:存放基本类型的变量数据和对象的应用,对象(new出来的对象)本身并不存在栈中,而是存放在堆中或者常量池中(字符串常量对象存放在常量池中);
常量池:存放基本类型常量和字符串常量。
对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
而对于字符串来说,其对象的引用都是存储在栈中的,如果是编译期已经创建好(即指用双引号定义的)的就存储在常量池中,如果是运行期(new出来的对象)则存储在堆中。对于equals相等的字符串,在常量池中是只有一份的,在堆中则有多份。
两个深入阅读的链接
字符串常量池: http://droidyue.com/blog/2014/12/21/string-literal-pool-in-java/
字符串拼接内部实现:http://droidyue.com/blog/2014/08/30/java-details-string-concatenation/