不可变字符串String
String对象是不可变的。查看 JDK 文档你就会发现,String 类中每一个看起来会修改 String 值的方法,实际上都是重新创建了一个String对象,以包含修改后的字符串内容。
字符串拼接方法
代码如下:
将上述代码反编译后,我筛选了一下,如下:
如果你看不懂字节码指令没关系,可以看我的这篇文章字节码指令
从这个例子中,编译器创建了一个StringBuilder对象,用以构造最早的String,并以每个字符串调用一次StringBuilder的append()方法,总共2次,然后就会调用toString方法来返回一个新的String对象。
代码如下:
将上述代码反编译后,我筛选了一下,如下:
反编译后好像看不了什么东西出来,因为concat也是java.lang.String里面的方法,所以的话我觉得可以直接去IDE看它的如何实现的。如下:
从concat的底部实现可以看到,其实它最终也是要new一个String对象的,所以前面为什么提到Sting的不可变性。顺便看看Arrays.copyOf的方法内部,如下:
代码如下:
StringBuffer底层实现原理如下:
继续深入看看append方法内部如下:
总结一小下,StringBuffer类继承了StringBufferAbstractStringBuilder,然后调用StringBufferAbstractStringBuilder类里面的那个append方法进行拼接字符串。append会直接拷贝字符到内部的字符数组中,如果字符数组长度不够,会进行扩展。
代码如下:
StringBuilder底层实现原理如下:
StringBuilder和StringBuffer类似的,区别就是在于StringBuffer是线程安全的,StringBuilder是线程不安全的。会发现StringBuffer调用append方法时,会比StringBuilder多了一个 toStringCache 字段。字段上的解释是返回最后一次toString的缓存值,一旦StringBuffer被修改就清除这个缓存值。而且StingBuffer的append方法中多了一个 synchronized 进行声明。
- StringUtils.join方法
这个建议看其他博主~
总结:效率比较 StringBuilder < StringBuffer < concat < + < StringUtils.join