Java面试 | 代码中创建了多少个字符串?换个思路解答
关于String对象创建的问题经常出现在Java的技术面试中,网上关于这个的原理解析已经很多了,这篇文章提供一个用idea来验证的方法,不需要记住复杂的原理和源码,好记好操作。”
基本原理
JVM会用一个字符串常量池来存储字符串,这个一般开发人员都知道了,原因就是String使用的太频繁了,重用肯定比创建新对象效率来的高。当然能够用常量池的基础是String一个不可变对象,一旦创建完成,就不可修改了。Java中创建String对象的方法有好几种,下面我们用idea来验证一下不同的写法到底会创建几个对象。
开始之前,先在idea中安装一个jclasslib插件,后面会用到。这个插件可以可视化展示class文件内容。

字符串对象创建
1. 代码中直接写字符串,比如String str = "abc";
这种方式。在idea中写一个测试方法,并且加上断点。Debug启动后,在Debug的Memory窗口就可以看到当前堆中的对象统计,Diff是指每次重新刷新后对象的数量变化。当前第一次进断点,所以Diff都是0。

点下一步,就可以看到,堆中新创建了1个String对象。那怎么确认这个对象是否在堆的常量池中的呢?可以在下面再加一行:

可以看到String str2 = "abc";执行完后,并没有创建新的String对象。所以第一行创建的String是在常量池中。
2. 使用字符串创建新字符串,如String str = new String("abc");

可以发现新创建了2个String对象。一个肯定是常量池的,另外一个就是当使用new String来创建字符串的时候,堆里还会有一个普通String对象。
3. 使用字符数组创建字符串, 如String str = new String(char[]);

同样只创建了一个String,继续验证是否放入常量池:

相对于第一行有2个对象创建,说明str2新创建了对象并放入了常量池。得出结论是使用字符数组创建String,不会放入常量池。
4. 多字符串连接,如String str = str0 + str1 + str2;

字符串连接后,新创建了一个对象。继续验证一下是否在常量池:

又新创建了一个String对象,说明字符串连接后也不会放入常量池。原因是什么呢?可以从编译出的class文件找到答案。
idea的target目录中找到编译出的class文件,点击“View->Show Bytecode With JclassLib”,如下图:

可以看到编译后的字符串连接其实使用StringBuilder实现的。那找到StringBuilder源代码的toString()方法,发现最终使用的是new String(char[])这个构造函数。所以最终的字符串不会进入常量池。
总结
String原理是面试中经常问道的问题,这篇文章用最简单的方式验证,是否好记很多呢?😄

