Java中build目录下concat编译文件为何比"+"方式更小?
String.concat()的编译文件体积更小,且运行时内存表现更优? 这个问题问得很到位!很多人默认字符串+拼接和concat()是一回事,但它们在编译实现和运行时内存行为上确实有明显差异,咱们一步步拆解清楚:
首先说编译文件体积差异的原因:
当你用+做字符串拼接时,Java编译器会自动把代码转换成StringBuilder的链式调用,对应你的示例代码,编译后的逻辑等价于:
System.out.println(new StringBuilder().append(www).append(company).append(country).toString());
这意味着编译后的字节码里会包含一堆额外指令:创建StringBuilder实例的指令、三次append方法调用、一次toString调用,整体指令数量更多,生成的class文件自然更大。
而用concat()的代码,编译后的字节码就是直接调用String.concat()方法的指令:
System.out.println(www.concat(company).concat(country));
这里没有StringBuilder相关的冗余代码,只是两次invokevirtual调用concat方法,指令数量少很多,所以编译出来的文件体积更小。
再解释运行时内存占用的差异:
你知道+会用到StringBuilder,但可能没注意到——StringBuilder本身是个额外的对象,它内部还维护着char数组、容量计数器等属性。虽然这个对象在拼接完成后会被快速回收,但在拼接过程中,它确实会占用额外的内存空间。
而concat()方法的实现是直接基于char数组的复制操作:
- 先计算两个字符串的总长度,创建一个新的char数组
- 把原字符串的char内容复制到新数组里
- 再把要拼接的字符串的char内容复制进去
- 最后返回一个新的
String实例
整个过程没有额外的辅助对象(比如StringBuilder),虽然两次concat()会生成一个中间String对象,但对比StringBuilder的额外开销,整体内存占用反而更低——尤其是在你示例这种固定次数的拼接场景下,这种差异会更明显。
补充一句:如果是循环里的大量字符串拼接,StringBuilder的性能和内存表现会远优于多次concat(),因为concat()每次都会创建新的String对象,而StringBuilder可以复用内部的char数组。但在固定次数的短拼接场景下,concat()确实在编译体积和内存占用上更有优势。
内容的提问来源于stack exchange,提问作者parvelmarv

