基础 | String、StringBuffer与StringBuilder

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分,我们不见不散!

丙子先生的宗旨是,每天以短篇幅讲高频面试题,不增加太多负担,但需要持之以恒。

能力有限,欢迎指教!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值