今天刚到公司,老板说,xxx你昨天写的那个代码有问题,这个时候到我纳闷了,我昨天明明测试了十几遍确保没有问题才下班的,况且已经项目昨晚已经上线了,于是乎,打开电脑从头到尾全部过了一遍,没有发现什么错误呀,但是领导说的有错误肯定有他的道理,硬着头皮继续找,找着找着,一段代码进入了我的眼帘,如下:
部分代码截图。这段代码虽然看起来没有什么错,记得之前我看过一篇文章,讲的是用+号拼接字符串的效率不高,难道是这个问题?带着疑问给老板发了QQ,果不其然,还真是说我这个。
以上纯属虚构,像我这样工作经验丰富的人怎么可能反这么低级的错误呢。
今天我们来说Java中常用的拼接字符串的方式,我们常用的是一般是+号进行拼接,例如:String类也提供了concat的效率要比+号拼接的形式快一些,可能大部分人还是会用+号拼接的形式,因为简单,直观。
我们知道final修饰的String 类,以及final修饰的char[] value,表示String类不可被继承,且value只能被初始化一次。这里的value变量其实就是存储了String字符串中的所有字符。String类的concat还是replace都是内部重新生成一个String对象的。String对象是不变的,如果用“+”对字符串进行修改,必然会导致String池中产生废弃的String对象。StringBuffer和StringBuilder类型的对象能反复被修改,不会遗留废弃的Stirng对象。
如果有大量拼接字符串的话建议用StringBuilder或者StringBuffer,前者线程不安全,后者线程安全。到这里可能就会有人问了,为什么StringBuilder要比+号和concat效率高,我们一起来看他底层的实现:
concat方法底层是通过数组进行扩容,再次new一个String对象,我们对知道,如果并发量大,拼接多,会造成大量的内存导致内存溢出。
StringBuffer或者StringBuilder内部维护了一个可变数组,每次append都是在扩容数组,只有在最后toString的时候才new一个String对象返回。
String 类不可变,内部维护的char[] 数组长度不可变,为final修饰,String类也是final修饰,不存在扩容。字符串拼接,截取,都会生成一个新的对象。频繁操作字符串效率低下,因为每次都会生成新的对象。
StringBuilder和StringBuffer 类内部维护可变长度char[] , 初始化数组容量为16,存在扩容, 其append拼接字符串方法内部调用System的native方法,进行数组的拷贝,不会重新生成新的StringBuilder对象。 其每次调用 toString方法而重新生成的String对象,不会共享StringBuilder对象内部的char[],会进行一次char[]的copy操作。
以上大概就这些了,如果您有更好的看法或者建议可以在评论区留言哦