• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

String、StringBuffer与StringBuilder

技术杂谈 勤劳的小蚂蚁 3个月前 (01-29) 71次浏览 已收录 0个评论 扫描二维码

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 = strd + 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”;
}

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:String、StringBuffer与StringBuilder
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00