回答思路:
阐述String概念理解
存在问题和设计考量
总结体现的两个特性
StringBuilder/StringBuffer相同点和不同点
三者使用场景总结
回答总结:
String是Java中非常常见且基础的类,用于字符串的构造和管理,它是Immutable类的经典实现,是final class,所有的属性也都是final的所以无法对内部数据进行修改,原生的保证了线程安全;JDK8及其以前,底层数据是用char数组进行存储的,JDK9之后是byte数组存储的;
String修改操作不当会产生大量的临时字符串,为了避免这样的问题,Java引入了字符串常量(位于JVM的方法区内部有一个运行时常量池,字符串经过.intern()方法放入常量池)。运行机制就是:创建字符串常量 -> 检查常量池是否存在相同的字符串对象 -> 如果有则直接引用 -> 如果没有才创建新的字符串并保存在常量池中(注:放入常量池是指直接赋值法,new的字符串不放入常量池);
上述体现String两个特性:
1.不可变,String对象一旦生成不能对它进行改变;
2.常量池,当两个String有相同值的时候常量池的设计大幅度节省内存空间;
StringBuilder/StringBuffer是因为String修改操作的局限性而产生的工具类,都实现了AbstractStringBuilder类(将字符串的剪裁、拼接等常用动作封装成方法定义),所以几乎拥有了一致的对外方法调用。虽然他们底层存储的数据结构与String相同,但不同的是他们可以改变对象的值(这里改变的原理和ArrayList扩容一致,所以合理预估大小可以提升性能),并且值改变了以后不影响对象引用;
StringBuilder/StringBuffer的区别在于StringBuffer是线程安全的,它保证线程安全的方式是粗暴的给每个方法实现都加上了synchronize关键字,因此StringBuffer的性能要低于StringBuffer;
综上分析,在使用场景上:
1. 字符串内容不常变化时用String类;
2.频繁执行字符串修改操作,且单线程场景时,更适合用StringBuilder;
3.频繁执行字符串操作,且多线程场景时,更适合用StringBuffer。
注:上文提到的常量池位置