String类作为Java中的常用类,是各大公司面试时非常喜欢问到的地方,主要是String类够基础,但基础中又会延伸出很多相关技术点,比如final关键字、Java内存分配、Java虚拟机、线程安全等。
今天就主要分析一下 「String、StringBuffer和StringBuilder类以及三者之间的联系与区别」,需要重点关注,如有问题也可留言交流。
你了解String类吗?
问题分析:该问题比较笼统,建议从修饰符、底层原理、常用方法和主要特性方面进行回答。
参考答案:
- 修饰符:String类是final的,即意味着其不能被继承,并且String类的成员方法都默认为final的。
- 底层原理:String类是采用char型数组来保存字符串的,可参看源代码:private final char value[];
- 常用方法:substring()、concat()、replace()等需要改变字符串的操作都不是在原有字符串上进行的,均需要重新生成新的字符串对象。
- 主要特性: 对String对象的任何改变都不影响原对象,因为其一经创建即不可变,相关的任何change操作都会生成新的对象。
String、StringBuffer与StringBuilder有什么区别?
问题分析:先来了解一下Java虚拟机对「string +=“hello”」的优化,优化结果为:
StringBuilder str = new StringBuilder(string);
str.append("hello");
str.toString();
这是因为StringBuilder类表示可变的字符序列,其效率比String类高很多。
而StringBuilder和StringBuffer类拥有的成员属性以及成员方法基本相同,区别是StringBuffer的成员方法被synchronized修饰,故StringBuffer类也表示可变的字符序列,但其是线程安全的,而StringBuilder类是线程不安全的。
参考答案:
- 线程安全,只有StringBuffer类是线程安全的,String类和StringBuffer类都是线程不安全的。
- 执行效率:通常情况下,StringBuilder > StringBuffer > String,但也有特例,具体如下:
String str = "hello"+ "world"; // 效率高,编译器会对其字符串的直接相加操作进行优化
StringBuilder st = new StringBuilder().append("hello").append("world");
优化策略如下:
- 直接相加:形如"I"+“love”+“java"的字符串相加操作,在编译期间即会被优化成"Ilovejava”,可以用javap -c命令反编译生成的class文件进行验证。
- 间接相加:即包含字符串引用的相加操作,形如s1+s2+s3,效率要比直接相加低,因为编译器不会对引用变量进行优化。
扩展面试题
问:String str = new String(“java”)创建了多少个对象?
答:准确来说,在类加载的过程中,该段代码在运行时常量池中创建了一个"java"对象,而在代码执行过程中在堆空间创建了一个String对象。故该段代码在运行期间仅创建了一个对象,但该段代码涉及到了两个String对象。
扩展:关于String类的笔试题(重点关注)
public static void main(String[] args) {
String stra = "hello2";
String strb = "hello" + 2; //在编译期间已被优化成"hello2"
System.out.println(stra == strb); //true
String strc = "hello2";
String strd = "hello";
String stre = strb + 2; //字符串引用不会在编译期间被优化
System.out.println(strc == stre); //false
String strf = "hello2";
final String strg = "hello"; //final修饰的变量编译时会在常量池保存一个副本
String strh = strg + 2; //对final变量的访问在编译期间都会直接被替代为真实的值
System.out.println(strf == strh); //true
String stri = "hello2";
final String strj = getHello(); //值是运行期间才确定的
String strk = strj + 2;
System.out.println(stri == strk); //false
}
public static String getHello() {
return "hello";
}
推荐阅读
欢迎关注
Java名企面试吧,每天10点24分,我们不见不散!
丙子先生的宗旨是,每天以短篇幅讲高频面试题,不增加太多负担,但需要持之以恒。
能力有限,欢迎指教!