面试题答案
一键面试性能区别
- String:
- 原理:String类是不可变类,一旦创建,其值就不能被改变。每次对String进行拼接操作时,都会创建一个新的String对象。例如:
这里实际上是先创建了一个包含“a”的String对象,然后在拼接“b”时,又创建了一个新的包含“ab”的String对象,原来的“a”对象就成为了垃圾对象等待垃圾回收。String str = "a"; str = str + "b";
- 性能:在频繁字符串拼接场景下,由于每次拼接都会创建新对象,开销很大,性能较差。因为频繁创建和销毁对象会增加内存开销和垃圾回收的压力。
- StringBuffer:
- 原理:StringBuffer类是可变类,它的对象可以被多次修改,而不产生新的未使用对象。它内部维护了一个字符数组,初始容量为16个字符,如果字符数组满了,会进行扩容。例如:
这里通过append方法直接在原有的StringBuffer对象上进行操作,不会创建新的对象。StringBuffer sb = new StringBuffer("a"); sb.append("b");
- 性能:在频繁字符串拼接场景下,性能比String好很多,因为它避免了频繁创建新对象。但是,由于它的方法大多是同步的(使用
synchronized
关键字修饰),以保证线程安全,所以在单线程环境下,这种同步机制会带来一些性能损耗。
- StringBuilder:
- 原理:与StringBuffer类似,也是可变类,同样通过维护一个字符数组来实现字符串的动态修改。例如:
也是在原对象上进行操作,不创建新对象。StringBuilder sb = new StringBuilder("a"); sb.append("b");
- 性能:在频繁字符串拼接场景下,性能最优。因为它与StringBuffer的主要区别在于它的方法不是同步的,在单线程环境下,没有同步带来的额外开销,所以在单线程频繁字符串拼接场景下,它的性能要优于StringBuffer。在多线程环境下,如果需要保证线程安全,就不能使用StringBuilder,而要使用StringBuffer。
综上所述,在频繁字符串拼接场景下,如果是单线程环境,优先选择StringBuilder;如果是多线程环境,优先选择StringBuffer;而String由于性能问题,不适合频繁拼接场景。